Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6c66e984 authored by Alice Yang's avatar Alice Yang Committed by Android (Google) Code Review
Browse files

Merge "New UI for account picker" into jb-dev

parents 5ab6e12b 727c5994
Loading
Loading
Loading
Loading
+115 −125
Original line number Diff line number Diff line
@@ -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 static final int SELECTED_ITEM_NONE = -1;

    private ArrayList<AccountInfo> mAccountInfos;
    private ArrayList<Account> 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 + ")");
        }

        // save some items we use frequently
        final AccountManager accountManager = AccountManager.get(this);
        final Intent intent = getIntent();

        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;
            }

        // 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);
        }

        // 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<String, AuthenticatorDescription> 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<AccountInfo>(accounts.length);
        mAccounts = new ArrayList<Account>(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<String>(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<Bundle> accountManagerFuture) {
        try {
            final Bundle accountManagerResult = accountManagerFuture.getResult();
@@ -385,34 +454,9 @@ public class ChooseTypeAndAccountActivity extends Activity
        finish();
    }

    private Drawable getDrawableForType(
            final HashMap<String, AuthenticatorDescription> 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<AccountInfo> {
        private LayoutInflater mLayoutInflater;
        private ArrayList<AccountInfo> mInfos;

        public AccountArrayAdapter(Context context, int textViewResourceId,
                ArrayList<AccountInfo> 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;
        }
    }
}
+1 −1
Original line number Diff line number Diff line
@@ -1983,7 +1983,7 @@
        <activity android:name="android.accounts.ChooseTypeAndAccountActivity"
                android:excludeFromRecents="true"
                android:exported="true"
                android:theme="@android:style/Theme.Holo.DialogWhenLarge.NoActionBar"
                android:theme="@android:style/Theme.Holo.Dialog"
                android:label="@string/choose_account_label"
                android:process=":ui">
        </activity>
+0 −46
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
-->

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:paddingLeft="0dip"
    android:paddingRight="0dip"
    android:orientation="horizontal" >

   <ImageView android:id="@+id/account_row_icon"
        android:layout_width="wrap_content"
        android:layout_height="fill_parent"
        android:paddingRight="8dip" />

   <TextView xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/account_row_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:gravity="center_vertical"
        android:minHeight="?android:attr/listPreferredItemHeight" />

    <ImageView android:id="@+id/account_row_checkmark"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:gravity="right"
         android:layout_weight="2"
         android:paddingRight="8dip"
         android:src="@drawable/ic_checkmark_holo_light" />
    
</LinearLayout>
 No newline at end of file
+26 −27
Original line number Diff line number Diff line
@@ -20,53 +20,52 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingLeft="16dip"
    android:paddingRight="16dip">

    <TextView android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:layout_gravity="left"
        android:text="@string/choose_account_label"
        android:paddingTop="16dip"
        android:paddingBottom="16dip"
        android:textColor="@android:color/holo_blue_light"
    />

    <View android:layout_height="3dip"
          android:layout_width="match_parent"
          android:background="#323232"/>
    android:orientation="vertical">

    <!-- Customizable description text -->
    <TextView android:id="@+id/description"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:layout_gravity="left|center_vertical"
        android:text="@string/choose_account_text"
        android:paddingTop="16dip"
        android:paddingBottom="16dip"
        android:paddingLeft="16dip"
        android:paddingRight="16dip"
    />

    <!-- List of accounts, with "Add new account" as the last item -->
    <ListView android:id="@android:id/list"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:drawSelectorOnTop="false"
        android:layout_weight="1"
        android:scrollbarAlwaysDrawVerticalTrack="true" />
        android:scrollbarAlwaysDrawVerticalTrack="true"
        android:choiceMode="singleChoice" />

    <!-- Horizontal divider line -->
    <View android:layout_height="1dip"
        android:layout_width="match_parent"
        android:background="?android:attr/dividerHorizontal" />

    <Button android:id="@+id/addAccount"
        style="?android:attr/buttonBarButtonStyle"
    <!-- Alert dialog style buttons along the bottom. -->
    <LinearLayout android:id="@+id/button_bar"
        style="?android:attr/buttonBarStyle"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="2dip"
        android:layout_marginRight="2dip"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:text="@string/add_account_button_label"
    />
        android:measureWithLargestChild="true">
        <Button android:id="@android:id/button1"
            style="?android:attr/buttonBarButtonStyle"
            android:layout_width="wrap_content" android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="@android:string/no"
            android:onClick="onCancelButtonClicked" />
        <Button android:id="@android:id/button2"
            style="?android:attr/buttonBarButtonStyle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="@android:string/yes"
            android:onClick="onOkButtonClicked" />
    </LinearLayout>
</LinearLayout>
+1 −3
Original line number Diff line number Diff line
@@ -28,7 +28,6 @@
       this.
  -->
  <java-symbol type="id" name="account_name" />
  <java-symbol type="id" name="account_row_checkmark" />
  <java-symbol type="id" name="account_row_icon" />
  <java-symbol type="id" name="account_row_text" />
  <java-symbol type="id" name="account_type" />
@@ -41,7 +40,6 @@
  <java-symbol type="id" name="action_menu_presenter" />
  <java-symbol type="id" name="action_mode_close_button" />
  <java-symbol type="id" name="activity_chooser_view_content" />
  <java-symbol type="id" name="addAccount" />
  <java-symbol type="id" name="albumart" />
  <java-symbol type="id" name="alertTitle" />
  <java-symbol type="id" name="allow_button" />
@@ -301,6 +299,7 @@
  <java-symbol type="dimen" name="notification_title_text_size" />
  <java-symbol type="dimen" name="notification_subtext_size" />

  <java-symbol type="string" name="add_account_button_label" />
  <java-symbol type="string" name="addToDictionary" />
  <java-symbol type="string" name="action_bar_home_description" />
  <java-symbol type="string" name="action_bar_up_description" />
@@ -1027,7 +1026,6 @@
  <java-symbol type="layout" name="choose_account" />
  <java-symbol type="layout" name="choose_account_row" />
  <java-symbol type="layout" name="choose_account_type" />
  <java-symbol type="layout" name="choose_selected_account_row" />
  <java-symbol type="layout" name="choose_type_and_account" />
  <java-symbol type="layout" name="grant_credentials_permission" />
  <java-symbol type="layout" name="number_picker" />
Loading