Merge "Changing spinner width to avoid truncation in other languages"
diff --git a/res/layout/user_profile_header.xml b/res/layout/user_profile_header.xml
deleted file mode 100644
index 828f08c..0000000
--- a/res/layout/user_profile_header.xml
+++ /dev/null
@@ -1,52 +0,0 @@
-<?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:id="@+id/user_profile_header"
- android:orientation="horizontal"
- android:layout_width="match_parent"
- android:layout_height="?attr/list_item_header_height"
- android:paddingLeft="?attr/list_item_padding_left"
- android:paddingRight="?attr/list_item_padding_right"
- android:paddingStart="?attr/list_item_padding_left"
- android:paddingEnd="?attr/list_item_padding_right"
- android:paddingTop="4dp"
- android:paddingBottom="8dp" >
-
- <TextView android:id="@+id/profile_title"
- android:layout_width="@dimen/contact_list_section_header_width"
- android:layout_height="?android:attr/listPreferredItemHeight"
- android:singleLine="true"
- android:text="@string/user_profile_contacts_list_header"
- android:ellipsize="end"
- android:textAppearance="@style/SectionHeaderStyle"
- android:gravity="start|center_vertical" />
-
- <Button android:id="@+id/user_profile_button"
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="?android:attr/listPreferredItemHeight"
- android:paddingStart="?attr/list_item_padding_left"
- android:paddingEnd="?attr/list_item_padding_right"
- android:background="?android:attr/selectableItemBackground"
- android:singleLine="true"
- android:text="@string/profile_display_name"
- android:ellipsize="end"
- android:gravity="start|center_vertical"
- android:textAppearance="?android:attr/textAppearanceMedium" />
-
-</LinearLayout>
diff --git a/res/values/donottranslate_config.xml b/res/values/donottranslate_config.xml
index 1c776ab..3428fa1 100644
--- a/res/values/donottranslate_config.xml
+++ b/res/values/donottranslate_config.xml
@@ -22,9 +22,6 @@
<!-- If true, phonetic name is included in the contact editor by default -->
<bool name="config_editor_include_phonetic_name">false</bool>
- <!-- If true, the "home" icon on the action bar will be shown. -->
- <bool name="show_home_icon">false</bool>
-
<!--
If true, the "view updates from group" button in the action bar will be
shown. Otherwise it will be part of the content on the group detail page.
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 1f6c80a..37e276f 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -624,10 +624,6 @@
<xliff:g id="call_type" example="Friends">%1$s</xliff:g> <xliff:g id="call_short_date" example="Friends">%2$s</xliff:g>
</string>
- <!-- Text displayed in place of the display name for the contact that represents the user's
- personal profile entry [CHAR LIMIT=64] -->
- <string name="profile_display_name">Set up my profile</string>
-
<!-- Label to instruct the user to type in a contact's name to add the contact as a member of the current group. [CHAR LIMIT=64] -->
<string name="enter_contact_name">Type person\'s name</string>
diff --git a/src/com/android/contacts/GroupMetaDataLoader.java b/src/com/android/contacts/GroupMetaDataLoader.java
index 8344041..47648b3 100644
--- a/src/com/android/contacts/GroupMetaDataLoader.java
+++ b/src/com/android/contacts/GroupMetaDataLoader.java
@@ -50,7 +50,7 @@
public GroupMetaDataLoader(Context context, Uri groupUri) {
super(context, ensureIsGroupUri(groupUri), COLUMNS, Groups.ACCOUNT_TYPE + " NOT NULL AND "
- + Groups.ACCOUNT_NAME + " NOT NULL", null, null);
+ + Groups.ACCOUNT_NAME + " NOT NULL", null, Groups.TITLE);
}
/**
diff --git a/src/com/android/contacts/activities/ActionBarAdapter.java b/src/com/android/contacts/activities/ActionBarAdapter.java
index febfa44..2d6740d 100644
--- a/src/com/android/contacts/activities/ActionBarAdapter.java
+++ b/src/com/android/contacts/activities/ActionBarAdapter.java
@@ -108,6 +108,7 @@
private final FrameLayout mToolBarFrame;
private boolean mShowHomeIcon;
+ private boolean mShowHomeAsUp;
public interface TabState {
public static int ALL = 0;
@@ -129,12 +130,19 @@
mToolbar = toolbar;
mToolBarFrame = (FrameLayout) mToolbar.getParent();
mMaxToolbarContentInsetStart = mToolbar.getContentInsetStart();
- mShowHomeIcon = mActivity.getResources().getBoolean(R.bool.show_home_icon);
setupSearchAndSelectionViews();
setupTabs(mActivity);
}
+ public void setShowHomeIcon(boolean showHomeIcon) {
+ mShowHomeIcon = showHomeIcon;
+ }
+
+ public void setShowHomeAsUp(boolean showHomeAsUp) {
+ mShowHomeAsUp = showHomeAsUp;
+ }
+
private void setupTabs(Context context) {
final TypedArray attributeArray = context.obtainStyledAttributes(
new int[]{android.R.attr.actionBarSize});
@@ -354,6 +362,9 @@
int newFlags = 0;
if (mShowHomeIcon && !isSearchOrSelectionMode) {
newFlags |= ActionBar.DISPLAY_SHOW_HOME;
+ if (mShowHomeAsUp) {
+ newFlags |= ActionBar.DISPLAY_HOME_AS_UP;
+ }
}
if (mSearchMode && !mSelectionMode) {
// The search container is placed inside the toolbar. So we need to disable the
diff --git a/src/com/android/contacts/activities/ContactSelectionActivity.java b/src/com/android/contacts/activities/ContactSelectionActivity.java
index c2951d8..50f50dd 100644
--- a/src/com/android/contacts/activities/ContactSelectionActivity.java
+++ b/src/com/android/contacts/activities/ContactSelectionActivity.java
@@ -290,7 +290,6 @@
case ContactsRequest.ACTION_DEFAULT:
case ContactsRequest.ACTION_PICK_CONTACT: {
ContactPickerFragment fragment = new ContactPickerFragment();
- fragment.setIncludeProfile(mRequest.shouldIncludeProfile());
fragment.setIncludeFavorites(mRequest.shouldIncludeFavorites());
mListFragment = fragment;
break;
diff --git a/src/com/android/contacts/activities/PeopleActivity.java b/src/com/android/contacts/activities/PeopleActivity.java
index eea55da..ac88619 100644
--- a/src/com/android/contacts/activities/PeopleActivity.java
+++ b/src/com/android/contacts/activities/PeopleActivity.java
@@ -93,7 +93,7 @@
import com.android.contacts.list.ContactsIntentResolver;
import com.android.contacts.list.ContactsRequest;
import com.android.contacts.list.ContactsUnavailableFragment;
-import com.android.contacts.list.MultiSelectContactsListFragment;
+import com.android.contacts.list.DefaultContactBrowseListFragment;
import com.android.contacts.list.MultiSelectContactsListFragment.OnCheckBoxListActionListener;
import com.android.contacts.list.OnContactBrowserActionListener;
import com.android.contacts.list.OnContactsUnavailableActionListener;
@@ -149,7 +149,7 @@
/**
* Showing a list of Contacts. Also used for showing search results in search mode.
*/
- private MultiSelectContactsListFragment mAllFragment;
+ private DefaultContactBrowseListFragment mAllFragment;
private GroupsFragment mGroupsFragment;
private AccountFiltersFragment mAccountFiltersFragment;
@@ -375,7 +375,7 @@
// However, if it's after screen rotation, the fragments have been re-created by
// the fragment manager, so first see if there're already the target fragments
// existing.
- mAllFragment = (MultiSelectContactsListFragment)
+ mAllFragment = (DefaultContactBrowseListFragment)
fragmentManager.findFragmentByTag(ALL_TAG);
mGroupsFragment = (GroupsFragment)
fragmentManager.findFragmentByTag(GROUPS_TAG);
@@ -383,7 +383,7 @@
fragmentManager.findFragmentByTag(FILTERS_TAG);
if (mAllFragment == null) {
- mAllFragment = new MultiSelectContactsListFragment();
+ mAllFragment = new DefaultContactBrowseListFragment();
transaction.add(R.id.tab_pager, mAllFragment, ALL_TAG);
if (areGroupWritableAccountsAvailable()) {
@@ -1310,14 +1310,8 @@
}
private void joinSelectedContacts() {
- final Long[] contactIdsArray = mAllFragment.getSelectedContactIds().toArray(
- new Long[mAllFragment.getSelectedContactIds().size()]);
- final long[] contactIdsArray2 = new long[contactIdsArray.length];
- for (int i = 0; i < contactIdsArray.length; i++) {
- contactIdsArray2[i] = contactIdsArray[i];
- }
- final Intent intent = ContactSaveService.createJoinSeveralContactsIntent(this,
- contactIdsArray2);
+ final Intent intent = ContactSaveService.createJoinSeveralContactsIntent(
+ this, mAllFragment.getSelectedContactIdsArray());
this.startService(intent);
mActionBarAdapter.setSelectionMode(false);
diff --git a/src/com/android/contacts/group/GroupMembersListAdapter.java b/src/com/android/contacts/group/GroupMembersListAdapter.java
index 71e8f8d..f208fc8 100644
--- a/src/com/android/contacts/group/GroupMembersListAdapter.java
+++ b/src/com/android/contacts/group/GroupMembersListAdapter.java
@@ -28,12 +28,12 @@
import android.view.ViewGroup;
import com.android.contacts.common.ContactPhotoManager.DefaultImageRequest;
-import com.android.contacts.common.list.ContactEntryListAdapter;
import com.android.contacts.common.list.ContactListItemView;
+import com.android.contacts.common.list.MultiSelectEntryContactListAdapter;
import com.android.contacts.common.preference.ContactsPreferences;
/** Group members cursor adapter. */
-public class GroupMembersListAdapter extends ContactEntryListAdapter {
+public class GroupMembersListAdapter extends MultiSelectEntryContactListAdapter {
private static class GroupMembersQuery {
@@ -67,7 +67,7 @@
private long mGroupId;
public GroupMembersListAdapter(Context context) {
- super(context);
+ super(context, GroupMembersQuery.CONTACT_ID);
mUnknownNameText = context.getText(android.R.string.unknownName);
setIndexedPartition(0);
}
diff --git a/src/com/android/contacts/group/GroupMembersListFragment.java b/src/com/android/contacts/group/GroupMembersListFragment.java
index b8dad5e..6fe206d 100644
--- a/src/com/android/contacts/group/GroupMembersListFragment.java
+++ b/src/com/android/contacts/group/GroupMembersListFragment.java
@@ -41,9 +41,10 @@
import com.android.contacts.common.model.AccountTypeManager;
import com.android.contacts.common.model.account.AccountType;
import com.android.contacts.interactions.GroupDeletionDialogFragment;
+import com.android.contacts.list.MultiSelectContactsListFragment;
/** Displays the members of a group. */
-public class GroupMembersListFragment extends ContactEntryListFragment<GroupMembersListAdapter> {
+public class GroupMembersListFragment extends MultiSelectContactsListFragment {
private static final String TAG = "GroupMembersList";
@@ -348,6 +349,11 @@
}
@Override
+ public GroupMembersListAdapter getAdapter() {
+ return (GroupMembersListAdapter) super.getAdapter();
+ }
+
+ @Override
protected void configureAdapter() {
super.configureAdapter();
if (mGroupMetadata != null) {
diff --git a/src/com/android/contacts/interactions/CallLogInteractionsLoader.java b/src/com/android/contacts/interactions/CallLogInteractionsLoader.java
index edecca0..d1dc8b4 100644
--- a/src/com/android/contacts/interactions/CallLogInteractionsLoader.java
+++ b/src/com/android/contacts/interactions/CallLogInteractionsLoader.java
@@ -52,17 +52,17 @@
@Override
public List<ContactInteraction> loadInBackground() {
- final boolean isPhoneNumbersEmpty = mPhoneNumbers == null || mPhoneNumbers.length <= 0;
- final boolean isSipNumbersEmpty = mSipNumbers == null || mSipNumbers.length <= 0;
+ final boolean hasPhoneNumber = mPhoneNumbers != null && mPhoneNumbers.length > 0;
+ final boolean hasSipNumber = mSipNumbers != null && mSipNumbers.length > 0;
if (!PermissionsUtil.hasPhonePermissions(getContext())
|| !getContext().getPackageManager()
.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)
- || (isPhoneNumbersEmpty && isSipNumbersEmpty) || mMaxToRetrieve <= 0) {
+ || (!hasPhoneNumber && !hasSipNumber) || mMaxToRetrieve <= 0) {
return Collections.emptyList();
}
final List<ContactInteraction> interactions = new ArrayList<>();
- if (!isPhoneNumbersEmpty) {
+ if (hasPhoneNumber) {
for (String number : mPhoneNumbers) {
final String normalizedNumber = PhoneNumberUtilsCompat.normalizeNumber(number);
if (!TextUtils.isEmpty(normalizedNumber)) {
@@ -70,7 +70,7 @@
}
}
}
- if (!isSipNumbersEmpty) {
+ if (hasSipNumber) {
for (String number : mSipNumbers) {
interactions.addAll(getCallLogInteractions(number));
}
@@ -90,7 +90,8 @@
}
});
// Duplicates only occur because of fuzzy matching. No need to dedupe a single number.
- if (mPhoneNumbers.length == 1) {
+ if ((hasPhoneNumber && mPhoneNumbers.length == 1 && !hasSipNumber)
+ || (hasSipNumber && mSipNumbers.length == 1 && !hasPhoneNumber)) {
return interactions;
}
return pruneDuplicateCallLogInteractions(interactions, mMaxToRetrieve);
diff --git a/src/com/android/contacts/list/ContactBrowseListFragment.java b/src/com/android/contacts/list/ContactBrowseListFragment.java
index afd2543..ea55333 100644
--- a/src/com/android/contacts/list/ContactBrowseListFragment.java
+++ b/src/com/android/contacts/list/ContactBrowseListFragment.java
@@ -36,7 +36,6 @@
import com.android.common.widget.CompositeCursorAdapter.Partition;
import com.android.contacts.common.list.AutoScrollListView;
-import com.android.contacts.common.list.ContactEntryListFragment;
import com.android.contacts.common.list.ContactListAdapter;
import com.android.contacts.common.list.ContactListFilter;
import com.android.contacts.common.list.DirectoryPartition;
@@ -49,7 +48,7 @@
* picking a contact with one of the PICK intents).
*/
public abstract class ContactBrowseListFragment extends
- ContactEntryListFragment<ContactListAdapter> {
+ MultiSelectContactsListFragment<ContactListAdapter> {
private static final String TAG = "ContactList";
@@ -383,6 +382,11 @@
}
@Override
+ public ContactListAdapter getAdapter() {
+ return (ContactListAdapter) super.getAdapter();
+ }
+
+ @Override
protected void configureAdapter() {
super.configureAdapter();
@@ -401,11 +405,8 @@
}
}
- // Display the user's profile if not in search mode
- adapter.setIncludeProfile(!searchMode);
-
- // Display favorites if not in search mode
- adapter.setIncludeFavorites(!searchMode);
+ adapter.setIncludeFavorites(!searchMode
+ && mFilter.filterType == ContactListFilter.FILTER_TYPE_ALL_ACCOUNTS);
}
@Override
diff --git a/src/com/android/contacts/list/ContactsRequest.java b/src/com/android/contacts/list/ContactsRequest.java
index f867549..a1428be 100644
--- a/src/com/android/contacts/list/ContactsRequest.java
+++ b/src/com/android/contacts/list/ContactsRequest.java
@@ -85,7 +85,6 @@
private CharSequence mTitle;
private boolean mSearchMode;
private String mQueryString;
- private boolean mIncludeProfile;
private boolean mIncludeFavorites;
private boolean mLegacyCompatibilityMode;
private boolean mDirectorySearchEnabled = true;
@@ -98,7 +97,6 @@
+ " mTitle=" + mTitle
+ " mSearchMode=" + mSearchMode
+ " mQueryString=" + mQueryString
- + " mIncludeProfile=" + mIncludeProfile
+ " mIncludeFavorites=" + mIncludeFavorites
+ " mLegacyCompatibilityMode=" + mLegacyCompatibilityMode
+ " mDirectorySearchEnabled=" + mDirectorySearchEnabled
@@ -146,14 +144,6 @@
mQueryString = string;
}
- public boolean shouldIncludeProfile() {
- return mIncludeProfile;
- }
-
- public void setIncludeProfile(boolean includeProfile) {
- mIncludeProfile = includeProfile;
- }
-
public boolean shouldIncludeFavorites() {
return mIncludeFavorites;
}
diff --git a/src/com/android/contacts/list/DefaultContactBrowseListFragment.java b/src/com/android/contacts/list/DefaultContactBrowseListFragment.java
index 2ce22c0..97bb86a 100644
--- a/src/com/android/contacts/list/DefaultContactBrowseListFragment.java
+++ b/src/com/android/contacts/list/DefaultContactBrowseListFragment.java
@@ -17,43 +17,29 @@
import android.content.Context;
import android.content.CursorLoader;
-import android.content.Intent;
import android.net.Uri;
import android.provider.ContactsContract.Contacts;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
-import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
-import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ListView;
import android.widget.TextView;
import com.android.contacts.R;
import com.android.contacts.common.list.ContactListAdapter;
-import com.android.contacts.common.list.ContactListFilter;
import com.android.contacts.common.list.ContactListItemView;
import com.android.contacts.common.list.DefaultContactListAdapter;
-import com.android.contacts.common.list.ProfileAndContactsLoader;
-import com.android.contacts.common.util.ImplicitIntentsUtil;
-import com.android.contacts.editor.ContactEditorFragment;
-import com.android.contacts.common.util.AccountFilterUtil;
+import com.android.contacts.common.list.FavoritesAndContactsLoader;
/**
* Fragment containing a contact list used for browsing (as compared to
* picking a contact with one of the PICK intents).
*/
public class DefaultContactBrowseListFragment extends ContactBrowseListFragment {
- private static final String TAG = DefaultContactBrowseListFragment.class.getSimpleName();
-
private View mSearchHeaderView;
- private View mAccountFilterHeader;
- private FrameLayout mProfileHeaderContainer;
- private View mProfileHeader;
- private Button mProfileMessage;
- private TextView mProfileTitle;
private View mSearchProgress;
private TextView mSearchProgressText;
@@ -68,7 +54,7 @@
@Override
public CursorLoader createCursorLoader(Context context) {
- return new ProfileAndContactsLoader(context);
+ return new FavoritesAndContactsLoader(context);
}
@Override
@@ -77,6 +63,10 @@
if (uri == null) {
return;
}
+ if (getAdapter().isDisplayingCheckBoxes()) {
+ super.onItemClick(position, id);
+ return;
+ }
viewContact(uri, getAdapter().isEnterpriseContact(position));
}
@@ -99,11 +89,6 @@
protected void onCreateView(LayoutInflater inflater, ViewGroup container) {
super.onCreateView(inflater, container);
- // Create an empty user profile header and hide it for now (it will be visible if the
- // contacts list will have no user profile).
- addEmptyUserProfileHeader(inflater);
- showEmptyUserProfile(false);
-
// Putting the header view inside a container will allow us to make
// it invisible later. See checkHeaderViewVisibility()
FrameLayout headerContainer = new FrameLayout(inflater.getContext());
@@ -138,70 +123,30 @@
}
@Override
- protected void setProfileHeader() {
- mUserProfileExists = getAdapter().hasProfile();
- showEmptyUserProfile(!mUserProfileExists && !isSearchMode());
+ protected void setListHeader() {
+ if (!isSearchMode()) {
+ return;
+ }
+ ContactListAdapter adapter = getAdapter();
+ if (adapter == null) {
+ return;
+ }
- if (isSearchMode()) {
- ContactListAdapter adapter = getAdapter();
- if (adapter == null) {
- return;
- }
-
- // In search mode we only display the header if there is nothing found
- if (TextUtils.isEmpty(getQueryString()) || !adapter.areAllPartitionsEmpty()) {
- mSearchHeaderView.setVisibility(View.GONE);
- showSearchProgress(false);
+ // In search mode we only display the header if there is nothing found
+ if (TextUtils.isEmpty(getQueryString()) || !adapter.areAllPartitionsEmpty()) {
+ mSearchHeaderView.setVisibility(View.GONE);
+ showSearchProgress(false);
+ } else {
+ mSearchHeaderView.setVisibility(View.VISIBLE);
+ if (adapter.isLoading()) {
+ mSearchProgressText.setText(R.string.search_results_searching);
+ showSearchProgress(true);
} else {
- mSearchHeaderView.setVisibility(View.VISIBLE);
- if (adapter.isLoading()) {
- mSearchProgressText.setText(R.string.search_results_searching);
- showSearchProgress(true);
- } else {
- mSearchProgressText.setText(R.string.listFoundAllContactsZero);
- mSearchProgressText.sendAccessibilityEvent(
- AccessibilityEvent.TYPE_VIEW_SELECTED);
- showSearchProgress(false);
- }
+ mSearchProgressText.setText(R.string.listFoundAllContactsZero);
+ mSearchProgressText.sendAccessibilityEvent(
+ AccessibilityEvent.TYPE_VIEW_SELECTED);
+ showSearchProgress(false);
}
- showEmptyUserProfile(false);
}
}
-
- private void showEmptyUserProfile(boolean show) {
- // Changing visibility of just the mProfileHeader doesn't do anything unless
- // you change visibility of its children, hence the call to mCounterHeaderView
- // and mProfileTitle
- mProfileHeaderContainer.setVisibility(show ? View.VISIBLE : View.GONE);
- mProfileHeader.setVisibility(show ? View.VISIBLE : View.GONE);
- mProfileTitle.setVisibility(show ? View.VISIBLE : View.GONE);
- mProfileMessage.setVisibility(show ? View.VISIBLE : View.GONE);
- }
-
- /**
- * This method creates a pseudo user profile contact. When the returned query doesn't have
- * a profile, this methods creates 2 views that are inserted as headers to the listview:
- * 1. A header view with the "ME" title and the contacts count.
- * 2. A button that prompts the user to create a local profile
- */
- private void addEmptyUserProfileHeader(LayoutInflater inflater) {
- ListView list = getListView();
- // Add a header with the "ME" name. The view is embedded in a frame view since you cannot
- // change the visibility of a view in a ListView without having a parent view.
- mProfileHeader = inflater.inflate(R.layout.user_profile_header, null, false);
- mProfileTitle = (TextView) mProfileHeader.findViewById(R.id.profile_title);
- mProfileHeaderContainer = new FrameLayout(inflater.getContext());
- mProfileHeaderContainer.addView(mProfileHeader);
- list.addHeaderView(mProfileHeaderContainer, null, false);
-
- // Add a button with a message inviting the user to create a local profile
- mProfileMessage = (Button) mProfileHeader.findViewById(R.id.user_profile_button);
- mProfileMessage.setOnClickListener(new View.OnClickListener() {
- public void onClick(View v) {
- Intent intent = new Intent(Intent.ACTION_INSERT, Contacts.CONTENT_URI);
- intent.putExtra(ContactEditorFragment.INTENT_EXTRA_NEW_LOCAL_PROFILE, true);
- ImplicitIntentsUtil.startActivityInApp(getActivity(), intent);
- }
- });
- }
-}
+}
\ No newline at end of file
diff --git a/src/com/android/contacts/list/MultiSelectContactsListFragment.java b/src/com/android/contacts/list/MultiSelectContactsListFragment.java
index 76dd3f3..53f5a74 100644
--- a/src/com/android/contacts/list/MultiSelectContactsListFragment.java
+++ b/src/com/android/contacts/list/MultiSelectContactsListFragment.java
@@ -16,18 +16,16 @@
package com.android.contacts.list;
-import com.android.contacts.common.list.ContactListAdapter;
-import com.android.contacts.common.list.ContactListItemView;
-import com.android.contacts.common.list.DefaultContactListAdapter;
+import com.android.contacts.common.list.ContactEntryListFragment;
+import com.android.contacts.common.list.MultiSelectEntryContactListAdapter;
+import com.android.contacts.common.list.MultiSelectEntryContactListAdapter.SelectedContactsListener;
import com.android.contacts.common.logging.SearchState;
-import com.android.contacts.list.MultiSelectEntryContactListAdapter.SelectedContactsListener;
import com.android.contacts.common.logging.Logger;
import android.database.Cursor;
-import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
-import android.text.TextUtils;
+import android.util.Log;
import android.view.accessibility.AccessibilityEvent;
import java.util.ArrayList;
@@ -38,9 +36,12 @@
* Fragment containing a contact list used for browsing contacts and optionally selecting
* multiple contacts via checkboxes.
*/
-public class MultiSelectContactsListFragment extends DefaultContactBrowseListFragment
+public abstract class MultiSelectContactsListFragment<T extends MultiSelectEntryContactListAdapter>
+ extends ContactEntryListFragment<T>
implements SelectedContactsListener {
+ private static final String TAG = "MultiContactsList";
+
public interface OnCheckBoxListActionListener {
void onStartDisplayingCheckBoxes();
void onSelectedContactIdsChanged();
@@ -60,7 +61,7 @@
/**
* Whether a search result was clicked by the user. Tracked so that we can distinguish
- * between exiting the search mode after a result was clicked from existing w/o clicking
+ * between exiting the search mode after a result was clicked from exiting w/o clicking
* any search result.
*/
public boolean wasSearchResultClicked() {
@@ -76,9 +77,7 @@
@Override
public void onSelectedContactsChanged() {
- if (mCheckBoxListListener != null) {
- mCheckBoxListListener.onSelectedContactIdsChanged();
- }
+ if (mCheckBoxListListener != null) mCheckBoxListListener.onSelectedContactIdsChanged();
}
@Override
@@ -106,13 +105,11 @@
}
public TreeSet<Long> getSelectedContactIds() {
- final MultiSelectEntryContactListAdapter adapter = getAdapter();
- return adapter.getSelectedContactIds();
+ return getAdapter().getSelectedContactIds();
}
- @Override
- public MultiSelectEntryContactListAdapter getAdapter() {
- return (MultiSelectEntryContactListAdapter) super.getAdapter();
+ public long[] getSelectedContactIdsArray() {
+ return getAdapter().getSelectedContactIdsArray();
}
@Override
@@ -129,9 +126,11 @@
}
public void displayCheckBoxes(boolean displayCheckBoxes) {
- getAdapter().setDisplayCheckBoxes(displayCheckBoxes);
- if (!displayCheckBoxes) {
- clearCheckBoxes();
+ if (getAdapter() != null) {
+ getAdapter().setDisplayCheckBoxes(displayCheckBoxes);
+ if (!displayCheckBoxes) {
+ clearCheckBoxes();
+ }
}
}
@@ -142,24 +141,20 @@
@Override
protected boolean onItemLongClick(int position, long id) {
final int previouslySelectedCount = getAdapter().getSelectedContactIds().size();
- final Uri uri = getAdapter().getContactUri(position);
+ final long contactId = getContactId(position);
final int partition = getAdapter().getPartitionForPosition(position);
- if (uri != null && (partition == ContactsContract.Directory.DEFAULT
- && (position > 0 || !getAdapter().hasProfile()))) {
- final String contactId = uri.getLastPathSegment();
- if (!TextUtils.isEmpty(contactId)) {
- if (mCheckBoxListListener != null) {
- mCheckBoxListListener.onStartDisplayingCheckBoxes();
- }
- getAdapter().toggleSelectionOfContactId(Long.valueOf(contactId));
- // Manually send clicked event if there is a checkbox.
- // See b/24098561. TalkBack will not read it otherwise.
- final int index = position + getListView().getHeaderViewsCount() - getListView()
- .getFirstVisiblePosition();
- if (index >= 0 && index < getListView().getChildCount()) {
- getListView().getChildAt(index).sendAccessibilityEvent(AccessibilityEvent
- .TYPE_VIEW_CLICKED);
- }
+ if (contactId >= 0 && partition == ContactsContract.Directory.DEFAULT) {
+ if (mCheckBoxListListener != null) {
+ mCheckBoxListListener.onStartDisplayingCheckBoxes();
+ }
+ getAdapter().toggleSelectionOfContactId(contactId);
+ // Manually send clicked event if there is a checkbox.
+ // See b/24098561. TalkBack will not read it otherwise.
+ final int index = position + getListView().getHeaderViewsCount() - getListView()
+ .getFirstVisiblePosition();
+ if (index >= 0 && index < getListView().getChildCount()) {
+ getListView().getChildAt(index).sendAccessibilityEvent(AccessibilityEvent
+ .TYPE_VIEW_CLICKED);
}
}
final int nowSelectedCount = getAdapter().getSelectedContactIds().size();
@@ -173,27 +168,37 @@
@Override
protected void onItemClick(int position, long id) {
- final Uri uri = getAdapter().getContactUri(position);
- if (uri == null) {
+ final long contactId = getContactId(position);
+ if (contactId < 0) {
return;
}
if (getAdapter().isDisplayingCheckBoxes()) {
- final String contactId = uri.getLastPathSegment();
- if (!TextUtils.isEmpty(contactId)) {
- getAdapter().toggleSelectionOfContactId(Long.valueOf(contactId));
- }
+ getAdapter().toggleSelectionOfContactId(contactId);
} else {
if (isSearchMode()) {
mSearchResultClicked = true;
Logger.logSearchEvent(createSearchStateForSearchResultClick(position));
}
- super.onItemClick(position, id);
}
if (mCheckBoxListListener != null && getAdapter().getSelectedContactIds().size() == 0) {
mCheckBoxListListener.onStopDisplayingCheckBoxes();
}
}
+ private long getContactId(int position) {
+ final int contactIdColumnIndex = getAdapter().getContactColumnIdIndex();
+
+ final Cursor cursor = (Cursor) getAdapter().getItem(position);
+ if (cursor != null) {
+ if (cursor.getColumnCount() > contactIdColumnIndex) {
+ return cursor.getLong(contactIdColumnIndex);
+ }
+ }
+
+ Log.w(TAG, "Failed to get contact ID from cursor column " + contactIdColumnIndex);
+ return -1;
+ }
+
/**
* Returns the state of the search results currently presented to the user.
*/
@@ -260,14 +265,4 @@
}
return searchState;
}
-
- @Override
- protected ContactListAdapter createListAdapter() {
- DefaultContactListAdapter adapter = new MultiSelectEntryContactListAdapter(getContext());
- adapter.setSectionHeaderDisplayEnabled(isSectionHeaderDisplayEnabled());
- adapter.setDisplayPhotos(true);
- adapter.setPhotoPosition(
- ContactListItemView.getDefaultPhotoPosition(/* opposite = */ false));
- return adapter;
- }
}
diff --git a/src/com/android/contacts/list/MultiSelectEntryContactListAdapter.java b/src/com/android/contacts/list/MultiSelectEntryContactListAdapter.java
deleted file mode 100644
index b080657..0000000
--- a/src/com/android/contacts/list/MultiSelectEntryContactListAdapter.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-package com.android.contacts.list;
-
-import com.android.contacts.common.list.ContactListItemView;
-import com.android.contacts.common.list.DefaultContactListAdapter;
-
-import android.content.Context;
-import android.database.Cursor;
-import android.provider.ContactsContract;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.CheckBox;
-
-import java.util.TreeSet;
-
-/**
- * An extension of the default contact adapter that adds checkboxes and the ability
- * to select multiple contacts.
- */
-public class MultiSelectEntryContactListAdapter extends DefaultContactListAdapter {
-
- private SelectedContactsListener mSelectedContactsListener;
- private TreeSet<Long> mSelectedContactIds = new TreeSet<Long>();
- private boolean mDisplayCheckBoxes;
-
- public interface SelectedContactsListener {
- void onSelectedContactsChanged();
- void onSelectedContactsChangedViaCheckBox();
- }
-
- public MultiSelectEntryContactListAdapter(Context context) {
- super(context);
- }
-
- public void setSelectedContactsListener(SelectedContactsListener listener) {
- mSelectedContactsListener = listener;
- }
-
- /**
- * Returns set of selected contacts.
- */
- public TreeSet<Long> getSelectedContactIds() {
- return mSelectedContactIds;
- }
-
- /**
- * Update set of selected contacts. This changes which checkboxes are set.
- */
- public void setSelectedContactIds(TreeSet<Long> selectedContactIds) {
- this.mSelectedContactIds = selectedContactIds;
- notifyDataSetChanged();
- if (mSelectedContactsListener != null) {
- mSelectedContactsListener.onSelectedContactsChanged();
- }
- }
-
- /**
- * Shows checkboxes beside contacts if {@param displayCheckBoxes} is {@code TRUE}.
- * Not guaranteed to work with all configurations of this adapter.
- */
- public void setDisplayCheckBoxes(boolean showCheckBoxes) {
- if (!mDisplayCheckBoxes && showCheckBoxes) {
- setSelectedContactIds(new TreeSet<Long>());
- }
- mDisplayCheckBoxes = showCheckBoxes;
- notifyDataSetChanged();
- if (mSelectedContactsListener != null) {
- mSelectedContactsListener.onSelectedContactsChanged();
- }
- }
-
- /**
- * Checkboxes are being displayed beside contacts.
- */
- public boolean isDisplayingCheckBoxes() {
- return mDisplayCheckBoxes;
- }
-
- /**
- * Toggle the checkbox beside the contact for {@param contactId}.
- */
- public void toggleSelectionOfContactId(long contactId) {
- if (mSelectedContactIds.contains(contactId)) {
- mSelectedContactIds.remove(contactId);
- } else {
- mSelectedContactIds.add(contactId);
- }
- notifyDataSetChanged();
- if (mSelectedContactsListener != null) {
- mSelectedContactsListener.onSelectedContactsChanged();
- }
- }
-
- @Override
- protected void bindView(View itemView, int partition, Cursor cursor, int position) {
- super.bindView(itemView, partition, cursor, position);
- final ContactListItemView view = (ContactListItemView) itemView;
- bindCheckBox(view, cursor, position, partition == ContactsContract.Directory.DEFAULT);
- }
-
- private void bindCheckBox(ContactListItemView view, Cursor cursor, int position,
- boolean isLocalDirectory) {
- // Disable clicking on the ME profile and all contacts from remote directories
- // when showing check boxes. We do this by telling the view to handle clicking itself.
- view.setClickable((position == 0 && hasProfile() || !isLocalDirectory)
- && mDisplayCheckBoxes);
- // Only show checkboxes if mDisplayCheckBoxes is enabled. Also, never show the
- // checkbox for the Me profile entry and other directory contacts except local directory.
- if (position == 0 && hasProfile() || !mDisplayCheckBoxes || !isLocalDirectory) {
- view.hideCheckBox();
- return;
- }
- final CheckBox checkBox = view.getCheckBox();
- final long contactId = cursor.getLong(ContactQuery.CONTACT_ID);
- checkBox.setChecked(mSelectedContactIds.contains(contactId));
- checkBox.setTag(contactId);
- checkBox.setOnClickListener(mCheckBoxClickListener);
- }
-
- private final OnClickListener mCheckBoxClickListener = new OnClickListener() {
- @Override
- public void onClick(View v) {
- final CheckBox checkBox = (CheckBox) v;
- final Long contactId = (Long) checkBox.getTag();
- if (checkBox.isChecked()) {
- mSelectedContactIds.add(contactId);
- } else {
- mSelectedContactIds.remove(contactId);
- }
- notifyDataSetChanged();
- if (mSelectedContactsListener != null) {
- mSelectedContactsListener.onSelectedContactsChangedViaCheckBox();
- }
- }
- };
-}