From 727c599454b1e280a237b10fea4dd7f7cb1096e0 Mon Sep 17 00:00:00 2001 From: Alice Yang Date: Tue, 29 May 2012 13:31:04 -0700 Subject: [PATCH] New UI for account picker - Added radio buttons to indicate the selected item - "Add account" is one of the list options instead of a button - Removed icons - Added "Cancel" and "OK" buttons - Use dialog theme - Omit description text by default Bug 6505441 Change-Id: I672a11481ee99e183142142bddf8f97b7b149d37 --- .../ChooseTypeAndAccountActivity.java | 248 +++++++++--------- core/res/AndroidManifest.xml | 2 +- .../layout/choose_selected_account_row.xml | 46 ---- .../res/layout/choose_type_and_account.xml | 53 ++-- core/res/res/values/public.xml | 4 +- core/res/res/values/strings.xml | 3 +- 6 files changed, 148 insertions(+), 208 deletions(-) delete mode 100644 core/res/res/layout/choose_selected_account_row.xml diff --git a/core/java/android/accounts/ChooseTypeAndAccountActivity.java b/core/java/android/accounts/ChooseTypeAndAccountActivity.java index 291e75ee4de00..85438487d22ee 100644 --- a/core/java/android/accounts/ChooseTypeAndAccountActivity.java +++ b/core/java/android/accounts/ChooseTypeAndAccountActivity.java @@ -16,24 +16,19 @@ package android.accounts; import android.app.Activity; -import android.content.Context; import android.content.Intent; -import android.content.pm.PackageManager; -import android.content.res.Resources; -import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.Parcelable; import android.text.TextUtils; import android.util.Log; -import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.Button; -import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; + import com.android.internal.R; import java.io.IOException; @@ -106,10 +101,16 @@ public class ChooseTypeAndAccountActivity extends Activity private static final String KEY_INSTANCE_STATE_PENDING_REQUEST = "pendingRequest"; private static final String KEY_INSTANCE_STATE_EXISTING_ACCOUNTS = "existingAccounts"; + private static final String KEY_INSTANCE_STATE_SELECTED_ACCOUNT_NAME = "selectedAccountName"; + private static final String KEY_INSTANCE_STATE_SELECTED_ADD_ACCOUNT = "selectedAddAccount"; - private ArrayList mAccountInfos; + private static final int SELECTED_ITEM_NONE = -1; + + private ArrayList mAccounts; private int mPendingRequest = REQUEST_NULL; private Parcelable[] mExistingAccounts = null; + private int mSelectedItemIndex; + private Button mOkButton; @Override public void onCreate(Bundle savedInstanceState) { @@ -119,30 +120,38 @@ public class ChooseTypeAndAccountActivity extends Activity + savedInstanceState + ")"); } - if (savedInstanceState != null) { - mPendingRequest = savedInstanceState.getInt(KEY_INSTANCE_STATE_PENDING_REQUEST); - mExistingAccounts = - savedInstanceState.getParcelableArray(KEY_INSTANCE_STATE_EXISTING_ACCOUNTS); - } else { - mPendingRequest = REQUEST_NULL; - mExistingAccounts = null; - } - // save some items we use frequently final AccountManager accountManager = AccountManager.get(this); final Intent intent = getIntent(); - // override the description text if supplied - final String descriptionOverride = - intent.getStringExtra(EXTRA_DESCRIPTION_TEXT_OVERRIDE); - if (!TextUtils.isEmpty(descriptionOverride)) { - ((TextView)findViewById(R.id.description)).setText(descriptionOverride); + String selectedAccountName = null; + boolean selectedAddNewAccount = false; + + if (savedInstanceState != null) { + mPendingRequest = savedInstanceState.getInt(KEY_INSTANCE_STATE_PENDING_REQUEST); + mExistingAccounts = + savedInstanceState.getParcelableArray(KEY_INSTANCE_STATE_EXISTING_ACCOUNTS); + + // Makes sure that any user selection is preserved across orientation changes. + selectedAccountName = savedInstanceState.getString( + KEY_INSTANCE_STATE_SELECTED_ACCOUNT_NAME); + + selectedAddNewAccount = savedInstanceState.getBoolean( + KEY_INSTANCE_STATE_SELECTED_ADD_ACCOUNT, false); + } else { + mPendingRequest = REQUEST_NULL; + mExistingAccounts = null; + // If the selected account as specified in the intent matches one in the list we will + // show is as pre-selected. + Account selectedAccount = (Account) intent.getParcelableExtra(EXTRA_SELECTED_ACCOUNT); + if (selectedAccount != null) { + selectedAccountName = selectedAccount.name; + } } - // If the selected account matches one in the list we will place a - // checkmark next to it. - final Account selectedAccount = - (Account)intent.getParcelableExtra(EXTRA_SELECTED_ACCOUNT); + if (Log.isLoggable(TAG, Log.VERBOSE)) { + Log.v(TAG, "selected account name is " + selectedAccountName); + } // build an efficiently queryable map of account types to authenticator descriptions final HashMap typeToAuthDescription = @@ -192,7 +201,8 @@ public class ChooseTypeAndAccountActivity extends Activity // accounts that don't match the allowable types, if provided, or that don't match the // allowable accounts, if provided. final Account[] accounts = accountManager.getAccounts(); - mAccountInfos = new ArrayList(accounts.length); + mAccounts = new ArrayList(accounts.length); + mSelectedItemIndex = SELECTED_ITEM_NONE; for (Account account : accounts) { if (setOfAllowableAccounts != null && !setOfAllowableAccounts.contains(account)) { @@ -202,15 +212,16 @@ public class ChooseTypeAndAccountActivity extends Activity && !setOfRelevantAccountTypes.contains(account.type)) { continue; } - mAccountInfos.add(new AccountInfo(account, - getDrawableForType(typeToAuthDescription, account.type), - account.equals(selectedAccount))); + if (account.name.equals(selectedAccountName)) { + mSelectedItemIndex = mAccounts.size(); + } + mAccounts.add(account); } if (mPendingRequest == REQUEST_NULL) { - // If there are no relevant accounts and only one relevant account typoe go directly to + // If there are no relevant accounts and only one relevant account type go directly to // add account. Otherwise let the user choose. - if (mAccountInfos.isEmpty()) { + if (mAccounts.isEmpty()) { if (setOfRelevantAccountTypes.size() == 1) { runAddAccountForAuthenticator(setOfRelevantAccountTypes.iterator().next()); } else { @@ -221,36 +232,71 @@ public class ChooseTypeAndAccountActivity extends Activity // if there is only one allowable account return it if (!intent.getBooleanExtra(EXTRA_ALWAYS_PROMPT_FOR_ACCOUNT, false) - && mAccountInfos.size() == 1) { - Account account = mAccountInfos.get(0).account; + && mAccounts.size() == 1) { + Account account = mAccounts.get(0); setResultAndFinish(account.name, account.type); return; } } + // Cannot set content view until we know that mPendingRequest is not null, otherwise + // would cause screen flicker. setContentView(R.layout.choose_type_and_account); - // there is more than one allowable account. initialize the list adapter to allow - // the user to select an account. + // Override the description text if supplied + final String descriptionOverride = + intent.getStringExtra(EXTRA_DESCRIPTION_TEXT_OVERRIDE); + TextView descriptionView = (TextView) findViewById(R.id.description); + if (!TextUtils.isEmpty(descriptionOverride)) { + descriptionView.setText(descriptionOverride); + } else { + descriptionView.setVisibility(View.GONE); + } + + // List of options includes all accounts found together with "Add new account" as the + // last item in the list. + String[] listItems = new String[mAccounts.size() + 1]; + for (int i = 0; i < mAccounts.size(); i++) { + listItems[i] = mAccounts.get(i).name; + } + listItems[mAccounts.size()] = getResources().getString( + R.string.add_account_button_label); + ListView list = (ListView) findViewById(android.R.id.list); - list.setAdapter(new AccountArrayAdapter(this, - android.R.layout.simple_list_item_1, mAccountInfos)); + list.setAdapter(new ArrayAdapter(this, + android.R.layout.simple_list_item_single_choice, listItems)); list.setChoiceMode(ListView.CHOICE_MODE_SINGLE); + list.setItemsCanFocus(false); list.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView parent, View v, int position, long id) { - onListItemClick((ListView)parent, v, position, id); + mSelectedItemIndex = position; + mOkButton.setEnabled(true); } }); - // set the listener for the addAccount button - Button addAccountButton = (Button) findViewById(R.id.addAccount); - addAccountButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(final View v) { - startChooseAccountTypeActivity(); + // If "Add account" option was previously selected by user, preserve it across + // orientation changes. + if (selectedAddNewAccount) { + mSelectedItemIndex = mAccounts.size(); + } + if (Log.isLoggable(TAG, Log.VERBOSE)) { + Log.v(TAG, "mSelectedItemIndex is " + mSelectedItemIndex); + } + + ViewGroup buttonBar = (ViewGroup) findViewById(R.id.button_bar); + if (buttonBar != null) { + mOkButton = (Button) buttonBar.findViewById(android.R.id.button2); + if (mSelectedItemIndex != SELECTED_ITEM_NONE) { + // If caller specified a selectedAccount, then display that as selected and enable + // the "OK" button by default. + list.setSelection(mSelectedItemIndex); + mOkButton.setEnabled(true); + } else { + // Otherwise "OK" button is disabled since nothing is pre-selected. + mOkButton.setEnabled(false); } - }); + } } @Override @@ -268,6 +314,28 @@ public class ChooseTypeAndAccountActivity extends Activity if (mPendingRequest == REQUEST_ADD_ACCOUNT) { outState.putParcelableArray(KEY_INSTANCE_STATE_EXISTING_ACCOUNTS, mExistingAccounts); } + if (mSelectedItemIndex != SELECTED_ITEM_NONE) { + if (mSelectedItemIndex == mAccounts.size()) { + outState.putBoolean(KEY_INSTANCE_STATE_SELECTED_ADD_ACCOUNT, true); + } else { + outState.putBoolean(KEY_INSTANCE_STATE_SELECTED_ADD_ACCOUNT, false); + outState.putString(KEY_INSTANCE_STATE_SELECTED_ACCOUNT_NAME, + mAccounts.get(mSelectedItemIndex).name); + } + } + } + + public void onCancelButtonClicked(View view) { + onBackPressed(); + } + + public void onOkButtonClicked(View view) { + if (mSelectedItemIndex == mAccounts.size()) { + // Selected "Add New Account" option + startChooseAccountTypeActivity(); + } else if (mSelectedItemIndex != SELECTED_ITEM_NONE) { + onAccountSelected(mAccounts.get(mSelectedItemIndex)); + } } // Called when the choose account type activity (for adding an account) returns. @@ -287,9 +355,9 @@ public class ChooseTypeAndAccountActivity extends Activity mPendingRequest = REQUEST_NULL; if (resultCode == RESULT_CANCELED) { - // if cancelling out of addAccount and the original state caused us to skip this, + // if canceling out of addAccount and the original state caused us to skip this, // finish this activity - if (mAccountInfos.isEmpty()) { + if (mAccounts.isEmpty()) { setResult(Activity.RESULT_CANCELED); finish(); } @@ -360,6 +428,7 @@ public class ChooseTypeAndAccountActivity extends Activity options, null /* activity */, this /* callback */, null /* Handler */); } + @Override public void run(final AccountManagerFuture accountManagerFuture) { try { final Bundle accountManagerResult = accountManagerFuture.getResult(); @@ -385,34 +454,9 @@ public class ChooseTypeAndAccountActivity extends Activity finish(); } - private Drawable getDrawableForType( - final HashMap typeToAuthDescription, - String accountType) { - Drawable icon = null; - if (typeToAuthDescription.containsKey(accountType)) { - try { - AuthenticatorDescription desc = typeToAuthDescription.get(accountType); - Context authContext = createPackageContext(desc.packageName, 0); - icon = authContext.getResources().getDrawable(desc.iconId); - } catch (PackageManager.NameNotFoundException e) { - // Nothing we can do much here, just log - if (Log.isLoggable(TAG, Log.WARN)) { - Log.w(TAG, "No icon name for account type " + accountType); - } - } catch (Resources.NotFoundException e) { - // Nothing we can do much here, just log - if (Log.isLoggable(TAG, Log.WARN)) { - Log.w(TAG, "No icon resource for account type " + accountType); - } - } - } - return icon; - } - - protected void onListItemClick(ListView l, View v, int position, long id) { - AccountInfo accountInfo = mAccountInfos.get(position); - Log.d(TAG, "selected account " + accountInfo.account); - setResultAndFinish(accountInfo.account.name, accountInfo.account.type); + private void onAccountSelected(Account account) { + Log.d(TAG, "selected account " + account); + setResultAndFinish(account.name, account.type); } private void setResultAndFinish(final String accountName, final String accountType) { @@ -444,58 +488,4 @@ public class ChooseTypeAndAccountActivity extends Activity startActivityForResult(intent, REQUEST_CHOOSE_TYPE); mPendingRequest = REQUEST_CHOOSE_TYPE; } - - private static class AccountInfo { - final Account account; - final Drawable drawable; - private final boolean checked; - - AccountInfo(Account account, Drawable drawable, boolean checked) { - this.account = account; - this.drawable = drawable; - this.checked = checked; - } - } - - private static class ViewHolder { - ImageView icon; - TextView text; - ImageView checkmark; - } - - private static class AccountArrayAdapter extends ArrayAdapter { - private LayoutInflater mLayoutInflater; - private ArrayList mInfos; - - public AccountArrayAdapter(Context context, int textViewResourceId, - ArrayList infos) { - super(context, textViewResourceId, infos); - mInfos = infos; - mLayoutInflater = (LayoutInflater) context.getSystemService( - Context.LAYOUT_INFLATER_SERVICE); - } - - @Override - public View getView(int position, View convertView, ViewGroup parent) { - ViewHolder holder; - - if (convertView == null) { - convertView = mLayoutInflater.inflate(R.layout.choose_selected_account_row, null); - holder = new ViewHolder(); - holder.text = (TextView) convertView.findViewById(R.id.account_row_text); - holder.icon = (ImageView) convertView.findViewById(R.id.account_row_icon); - holder.checkmark = (ImageView) convertView.findViewById(R.id.account_row_checkmark); - convertView.setTag(holder); - } else { - holder = (ViewHolder) convertView.getTag(); - } - - holder.text.setText(mInfos.get(position).account.name); - holder.icon.setImageDrawable(mInfos.get(position).drawable); - final int displayCheckmark = - mInfos.get(position).checked ? View.VISIBLE : View.INVISIBLE; - holder.checkmark.setVisibility(displayCheckmark); - return convertView; - } - } } diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index e3082ea77a3ac..155e59c01209d 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -1983,7 +1983,7 @@ diff --git a/core/res/res/layout/choose_selected_account_row.xml b/core/res/res/layout/choose_selected_account_row.xml deleted file mode 100644 index d88750dcc28b2..0000000000000 --- a/core/res/res/layout/choose_selected_account_row.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/core/res/res/layout/choose_type_and_account.xml b/core/res/res/layout/choose_type_and_account.xml index d7068b7bf44fe..9d1d28405e939 100644 --- a/core/res/res/layout/choose_type_and_account.xml +++ b/core/res/res/layout/choose_type_and_account.xml @@ -20,53 +20,52 @@ - - - - + android:orientation="vertical"> + + + android:scrollbarAlwaysDrawVerticalTrack="true" + android:choiceMode="singleChoice" /> + -