GroupMemberPickerFragment.java revision 6c5a5580c49db0e3cc5372beec82231e0aa76901
1/* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16package com.android.contacts.list; 17 18import android.content.Loader; 19import android.database.Cursor; 20import android.database.CursorWrapper; 21import android.os.Bundle; 22import android.util.Log; 23import android.view.LayoutInflater; 24import android.view.View; 25import android.view.ViewGroup; 26 27import com.android.contacts.common.R; 28import com.android.contacts.common.list.ContactEntryListFragment; 29import com.android.contacts.common.list.ContactListAdapter.ContactQuery; 30import com.android.contacts.common.list.ContactListFilter; 31import com.android.contacts.common.list.DefaultContactListAdapter; 32 33import java.util.ArrayList; 34 35/** 36 * Fragment containing raw contacts for a specified account that are not already in a group. 37 */ 38public class GroupMemberPickerFragment extends 39 ContactEntryListFragment<DefaultContactListAdapter> { 40 41 public static final String TAG = "GroupMemberPicker"; 42 43 private static final String KEY_ACCOUNT_NAME = "accountName"; 44 private static final String KEY_ACCOUNT_TYPE = "accountType"; 45 private static final String KEY_ACCOUNT_DATA_SET = "accountDataSet"; 46 private static final String KEY_RAW_CONTACT_IDS = "rawContactIds"; 47 48 private static final String ARG_ACCOUNT_NAME = "accountName"; 49 private static final String ARG_ACCOUNT_TYPE = "accountType"; 50 private static final String ARG_ACCOUNT_DATA_SET = "accountDataSet"; 51 private static final String ARG_RAW_CONTACT_IDS = "rawContactIds"; 52 53 /** Callbacks for host of {@link GroupMemberPickerFragment}. */ 54 public interface Listener { 55 56 /** Invoked when a potential group member is selected. */ 57 void onGroupMemberClicked(long contactId); 58 } 59 60 /** 61 * Filters out raw contacts that are already in the group and also handles queries for contact 62 * photo IDs and lookup keys which cannot be retrieved from the raw contact table directly. 63 */ 64 private class FilterCursorWrapper extends CursorWrapper { 65 66 private int[] mIndex; 67 private int mCount = 0; 68 private int mPos = 0; 69 70 public FilterCursorWrapper(Cursor cursor) { 71 super(cursor); 72 73 mCount = super.getCount(); 74 mIndex = new int[mCount]; 75 76 if (Log.isLoggable(TAG, Log.VERBOSE)) { 77 Log.v(TAG, "FilterCursorWrapper starting cursor size is " + mCount); 78 } 79 80 for (int i = 0; i < mCount; i++) { 81 super.moveToPosition(i); 82 final String contactId = getString(ContactQuery.CONTACT_ID); 83 if (!mRawContactIds.contains(contactId)) { 84 mIndex[mPos++] = i; 85 } 86 } 87 mCount = mPos; 88 mPos = 0; 89 super.moveToFirst(); 90 91 if (Log.isLoggable(TAG, Log.VERBOSE)) { 92 Log.v(TAG, "FilterCursorWrapper ending cursor size is" + mCount); 93 } 94 } 95 96 @Override 97 public boolean move(int offset) { 98 return moveToPosition(mPos + offset); 99 } 100 101 @Override 102 public boolean moveToNext() { 103 return moveToPosition(mPos + 1); 104 } 105 106 @Override 107 public boolean moveToPrevious() { 108 return moveToPosition(mPos - 1); 109 } 110 111 @Override 112 public boolean moveToFirst() { 113 return moveToPosition(0); 114 } 115 116 @Override 117 public boolean moveToLast() { 118 return moveToPosition(mCount - 1); 119 } 120 121 @Override 122 public boolean moveToPosition(int position) { 123 if (position >= mCount || position < 0) return false; 124 return super.moveToPosition(mIndex[position]); 125 } 126 127 @Override 128 public int getCount() { 129 return mCount; 130 } 131 132 @Override 133 public int getPosition() { 134 return mPos; 135 } 136 } 137 138 private String mAccountName; 139 private String mAccountType; 140 private String mAccountDataSet; 141 private ArrayList<String> mRawContactIds; 142 private Listener mListener; 143 144 public static GroupMemberPickerFragment newInstance(String accountName, String accountType, 145 String accountDataSet, ArrayList<String> rawContactIds) { 146 final Bundle args = new Bundle(); 147 args.putString(ARG_ACCOUNT_NAME, accountName); 148 args.putString(ARG_ACCOUNT_TYPE, accountType); 149 args.putString(ARG_ACCOUNT_DATA_SET, accountDataSet); 150 args.putStringArrayList(ARG_RAW_CONTACT_IDS, rawContactIds); 151 152 final GroupMemberPickerFragment fragment = new GroupMemberPickerFragment(); 153 fragment.setArguments(args); 154 return fragment; 155 } 156 157 public GroupMemberPickerFragment() { 158 setPhotoLoaderEnabled(true); 159 setSectionHeaderDisplayEnabled(false); 160 setVisibleScrollbarEnabled(true); 161 162 setHasOptionsMenu(true); 163 } 164 165 @Override 166 public void onCreate(Bundle savedState) { 167 if (savedState == null) { 168 mAccountName = getArguments().getString(ARG_ACCOUNT_NAME); 169 mAccountType = getArguments().getString(ARG_ACCOUNT_TYPE); 170 mAccountDataSet = getArguments().getString(ARG_ACCOUNT_DATA_SET); 171 mRawContactIds = getArguments().getStringArrayList(ARG_RAW_CONTACT_IDS); 172 } else { 173 mAccountName = savedState.getString(KEY_ACCOUNT_NAME); 174 mAccountType = savedState.getString(KEY_ACCOUNT_TYPE); 175 mAccountDataSet = savedState.getString(KEY_ACCOUNT_DATA_SET); 176 mRawContactIds = savedState.getStringArrayList(KEY_RAW_CONTACT_IDS); 177 } 178 super.onCreate(savedState); 179 } 180 181 @Override 182 public void onSaveInstanceState(Bundle outState) { 183 super.onSaveInstanceState(outState); 184 outState.putString(KEY_ACCOUNT_NAME, mAccountName); 185 outState.putString(KEY_ACCOUNT_TYPE, mAccountType); 186 outState.putString(KEY_ACCOUNT_DATA_SET, mAccountDataSet); 187 outState.putStringArrayList(KEY_RAW_CONTACT_IDS, mRawContactIds); 188 } 189 190 public void setListener(Listener listener) { 191 mListener = listener; 192 } 193 194 @Override 195 protected View inflateView(LayoutInflater inflater, ViewGroup container) { 196 return inflater.inflate(R.layout.contact_list_content, null); 197 } 198 199 @Override 200 public void onLoadFinished(Loader<Cursor> loader, Cursor data) { 201 if (data != null) { 202 super.onLoadFinished(loader, new FilterCursorWrapper(data)); 203 } 204 } 205 206 @Override 207 protected DefaultContactListAdapter createListAdapter() { 208 final DefaultContactListAdapter adapter = new DefaultContactListAdapter(getActivity()); 209 adapter.setFilter(ContactListFilter.createGroupMembersFilter( 210 mAccountType, mAccountName, mAccountDataSet)); 211 adapter.setSectionHeaderDisplayEnabled(true); 212 adapter.setDisplayPhotos(true); 213 return adapter; 214 } 215 216 @Override 217 protected void onItemClick(int position, long id) { 218 if (mListener != null) { 219 final long contactId = getAdapter().getContactId(position); 220 if (contactId > 0) { 221 mListener.onGroupMemberClicked(contactId); 222 } 223 } 224 } 225} 226