blob: 657451fb58eae7bcb0251f44b9053856bb055fe0 [file] [log] [blame]
Brian Attwell20510ec2015-02-27 16:10:45 -08001/*
2 * Copyright (C) 2015 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 */
16
17package com.android.contacts.list;
18
Gary Mai967cffd2016-08-01 16:54:25 -070019import android.content.Context;
20import android.database.Cursor;
21import android.graphics.drawable.Drawable;
22import android.os.Bundle;
23import android.provider.ContactsContract;
Aravind Sreekumar71212852018-04-06 15:47:45 -070024import androidx.core.view.ViewCompat;
Gary Mai967cffd2016-08-01 16:54:25 -070025import android.util.Log;
26import android.view.LayoutInflater;
27import android.view.View;
28import android.view.ViewGroup;
29import android.view.accessibility.AccessibilityEvent;
30import android.view.animation.Animation;
31import android.view.animation.AnimationUtils;
32import android.widget.AbsListView;
33import android.widget.ImageView;
34import android.widget.TextView;
35
Wenyi Wang1114fde2016-07-11 21:44:02 -070036import com.android.contacts.R;
Wenyi Wang79675452016-08-17 10:43:28 -070037import com.android.contacts.activities.ActionBarAdapter;
Gary Mai0a49afa2016-12-05 15:53:58 -080038import com.android.contacts.group.GroupMembersFragment;
Gary Mai69c182a2016-12-05 13:07:03 -080039import com.android.contacts.list.MultiSelectEntryContactListAdapter.SelectedContactsListener;
40import com.android.contacts.logging.ListEvent.ActionType;
41import com.android.contacts.logging.Logger;
42import com.android.contacts.logging.SearchState;
43import com.android.contacts.model.AccountTypeManager;
44import com.android.contacts.model.account.AccountType;
45import com.android.contacts.model.account.AccountWithDataSet;
46import com.android.contacts.model.account.GoogleAccountType;
yingrenw91f15e02018-01-17 17:03:15 +080047import com.android.contacts.model.account.SimAccountType;
Brian Attwell20510ec2015-02-27 16:10:45 -080048
Walter Janga84fe612016-01-13 16:49:04 -080049import java.util.ArrayList;
50import java.util.List;
Brian Attwell20510ec2015-02-27 16:10:45 -080051import java.util.TreeSet;
52
53/**
54 * Fragment containing a contact list used for browsing contacts and optionally selecting
55 * multiple contacts via checkboxes.
56 */
Walter Jange9ea4f02016-05-10 09:39:46 -070057public abstract class MultiSelectContactsListFragment<T extends MultiSelectEntryContactListAdapter>
58 extends ContactEntryListFragment<T>
Brian Attwell20510ec2015-02-27 16:10:45 -080059 implements SelectedContactsListener {
60
Gary Mai967cffd2016-08-01 16:54:25 -070061 protected boolean mAnimateOnLoad;
Walter Jang9c1fa5d2016-05-17 09:04:40 -070062 private static final String TAG = "MultiContactsList";
63
Brian Attwell20510ec2015-02-27 16:10:45 -080064 public interface OnCheckBoxListActionListener {
65 void onStartDisplayingCheckBoxes();
66 void onSelectedContactIdsChanged();
Brian Attwell8f8937f2015-03-05 14:07:43 -080067 void onStopDisplayingCheckBoxes();
Brian Attwell20510ec2015-02-27 16:10:45 -080068 }
69
70 private static final String EXTRA_KEY_SELECTED_CONTACTS = "selected_contacts";
yingrenw91f15e02018-01-17 17:03:15 +080071 private static final String EXTRA_KEY_SELECTED_SIM_CONTACT ="selected_sim";
Brian Attwell20510ec2015-02-27 16:10:45 -080072
73 private OnCheckBoxListActionListener mCheckBoxListListener;
74
75 public void setCheckBoxListListener(OnCheckBoxListActionListener checkBoxListListener) {
76 mCheckBoxListListener = checkBoxListListener;
77 }
78
Gary Mai967cffd2016-08-01 16:54:25 -070079 public void setAnimateOnLoad(boolean shouldAnimate) {
80 mAnimateOnLoad = shouldAnimate;
81 }
82
Brian Attwell20510ec2015-02-27 16:10:45 -080083 @Override
84 public void onSelectedContactsChanged() {
Walter Jang9c1fa5d2016-05-17 09:04:40 -070085 if (mCheckBoxListListener != null) mCheckBoxListListener.onSelectedContactIdsChanged();
Brian Attwell20510ec2015-02-27 16:10:45 -080086 }
87
88 @Override
Gary Mai967cffd2016-08-01 16:54:25 -070089 public View onCreateView(LayoutInflater inflater, ViewGroup container,
90 Bundle savedInstanceState) {
91 super.onCreateView(inflater, container, savedInstanceState);
92 if (savedInstanceState == null && mAnimateOnLoad) {
93 setLayoutAnimation(getListView(), R.anim.slide_and_fade_in_layout_animation);
94 }
95 return getView();
96 }
97
98 @Override
Brian Attwell20510ec2015-02-27 16:10:45 -080099 public void onActivityCreated(Bundle savedInstanceState) {
100 super.onActivityCreated(savedInstanceState);
101 if (savedInstanceState != null) {
102 final TreeSet<Long> selectedContactIds = (TreeSet<Long>)
103 savedInstanceState.getSerializable(EXTRA_KEY_SELECTED_CONTACTS);
yingrenw91f15e02018-01-17 17:03:15 +0800104 final int selectSimContact = savedInstanceState
105 .getInt(EXTRA_KEY_SELECTED_SIM_CONTACT);
Brian Attwell20510ec2015-02-27 16:10:45 -0800106 getAdapter().setSelectedContactIds(selectedContactIds);
yingrenw91f15e02018-01-17 17:03:15 +0800107 getAdapter().setSelectedSimContact(selectSimContact);
Brian Attwell20510ec2015-02-27 16:10:45 -0800108 }
109 }
110
Wenyi Wang6927bf32016-08-15 18:31:24 -0700111 @Override
112 public void onStart() {
113 super.onStart();
114 if (mCheckBoxListListener != null) {
115 mCheckBoxListListener.onSelectedContactIdsChanged();
116 }
117 }
118
Brian Attwell20510ec2015-02-27 16:10:45 -0800119 public TreeSet<Long> getSelectedContactIds() {
Walter Jang9c1fa5d2016-05-17 09:04:40 -0700120 return getAdapter().getSelectedContactIds();
121 }
122
123 public long[] getSelectedContactIdsArray() {
124 return getAdapter().getSelectedContactIdsArray();
Brian Attwell20510ec2015-02-27 16:10:45 -0800125 }
126
yingrenw91f15e02018-01-17 17:03:15 +0800127 public int getSelectedSimContact() {
128 return getAdapter().getSelectedSimContact();
129 }
130
Brian Attwell20510ec2015-02-27 16:10:45 -0800131 @Override
Brian Attwell20510ec2015-02-27 16:10:45 -0800132 protected void configureAdapter() {
133 super.configureAdapter();
134 getAdapter().setSelectedContactsListener(this);
135 }
136
137 @Override
138 public void onSaveInstanceState(Bundle outState) {
139 super.onSaveInstanceState(outState);
140 outState.putSerializable(EXTRA_KEY_SELECTED_CONTACTS, getSelectedContactIds());
yingrenw91f15e02018-01-17 17:03:15 +0800141 outState.putInt(EXTRA_KEY_SELECTED_SIM_CONTACT, getSelectedSimContact());
Brian Attwell20510ec2015-02-27 16:10:45 -0800142 }
143
144 public void displayCheckBoxes(boolean displayCheckBoxes) {
Walter Jang9c1fa5d2016-05-17 09:04:40 -0700145 if (getAdapter() != null) {
146 getAdapter().setDisplayCheckBoxes(displayCheckBoxes);
147 if (!displayCheckBoxes) {
148 clearCheckBoxes();
149 }
Brian Attwell20510ec2015-02-27 16:10:45 -0800150 }
151 }
Brian Attwelld2962a32015-03-02 14:48:50 -0800152
153 public void clearCheckBoxes() {
154 getAdapter().setSelectedContactIds(new TreeSet<Long>());
155 }
156
Brian Attwell20510ec2015-02-27 16:10:45 -0800157 @Override
158 protected boolean onItemLongClick(int position, long id) {
Brian Attwell8f8937f2015-03-05 14:07:43 -0800159 final int previouslySelectedCount = getAdapter().getSelectedContactIds().size();
Walter Jang9c1fa5d2016-05-17 09:04:40 -0700160 final long contactId = getContactId(position);
Tingting Wang80dfab32015-07-29 14:42:40 -0700161 final int partition = getAdapter().getPartitionForPosition(position);
yingrenw91f15e02018-01-17 17:03:15 +0800162 final boolean simContact = isSimContact(position);
Walter Jang9c1fa5d2016-05-17 09:04:40 -0700163 if (contactId >= 0 && partition == ContactsContract.Directory.DEFAULT) {
164 if (mCheckBoxListListener != null) {
165 mCheckBoxListListener.onStartDisplayingCheckBoxes();
166 }
yingrenw91f15e02018-01-17 17:03:15 +0800167 getAdapter().toggleSelectionOfContactId(contactId, simContact);
Wenyi Wang2b943992016-05-20 17:21:35 -0700168 Logger.logListEvent(ActionType.SELECT, getListType(),
169 /* count */ getAdapter().getCount(), /* clickedIndex */ position,
170 /* numSelected */ 1);
Walter Jang9c1fa5d2016-05-17 09:04:40 -0700171 // Manually send clicked event if there is a checkbox.
Wenyi Wang2b943992016-05-20 17:21:35 -0700172 // See b/24098561. TalkBack will not read it otherwise.
Walter Jang9c1fa5d2016-05-17 09:04:40 -0700173 final int index = position + getListView().getHeaderViewsCount() - getListView()
174 .getFirstVisiblePosition();
175 if (index >= 0 && index < getListView().getChildCount()) {
176 getListView().getChildAt(index).sendAccessibilityEvent(AccessibilityEvent
177 .TYPE_VIEW_CLICKED);
Brian Attwellc00112f2015-03-02 18:32:35 -0800178 }
Brian Attwell20510ec2015-02-27 16:10:45 -0800179 }
Brian Attwell8f8937f2015-03-05 14:07:43 -0800180 final int nowSelectedCount = getAdapter().getSelectedContactIds().size();
181 if (mCheckBoxListListener != null
182 && previouslySelectedCount != 0 && nowSelectedCount == 0) {
183 // Last checkbox has been unchecked. So we should stop displaying checkboxes.
184 mCheckBoxListListener.onStopDisplayingCheckBoxes();
185 }
Brian Attwell20510ec2015-02-27 16:10:45 -0800186 return true;
187 }
188
189 @Override
190 protected void onItemClick(int position, long id) {
Walter Jang9c1fa5d2016-05-17 09:04:40 -0700191 final long contactId = getContactId(position);
yingrenw91f15e02018-01-17 17:03:15 +0800192 final boolean simContact = isSimContact(position);
Walter Jang9c1fa5d2016-05-17 09:04:40 -0700193 if (contactId < 0) {
Brian Attwell20510ec2015-02-27 16:10:45 -0800194 return;
195 }
196 if (getAdapter().isDisplayingCheckBoxes()) {
yingrenw91f15e02018-01-17 17:03:15 +0800197 getAdapter().toggleSelectionOfContactId(contactId, simContact);
Brian Attwell20510ec2015-02-27 16:10:45 -0800198 }
Brian Attwell8f8937f2015-03-05 14:07:43 -0800199 if (mCheckBoxListListener != null && getAdapter().getSelectedContactIds().size() == 0) {
200 mCheckBoxListListener.onStopDisplayingCheckBoxes();
201 }
Brian Attwell20510ec2015-02-27 16:10:45 -0800202 }
203
Walter Jang9c1fa5d2016-05-17 09:04:40 -0700204 private long getContactId(int position) {
205 final int contactIdColumnIndex = getAdapter().getContactColumnIdIndex();
206
207 final Cursor cursor = (Cursor) getAdapter().getItem(position);
208 if (cursor != null) {
209 if (cursor.getColumnCount() > contactIdColumnIndex) {
210 return cursor.getLong(contactIdColumnIndex);
211 }
212 }
213
214 Log.w(TAG, "Failed to get contact ID from cursor column " + contactIdColumnIndex);
215 return -1;
216 }
217
yingrenw91f15e02018-01-17 17:03:15 +0800218 private boolean isSimContact(int position) {
219 final Cursor cursor = (Cursor) getAdapter().getItem(position);
220 final int accountTypeColumnIndex = cursor
221 .getColumnIndex(ContactsContract.RawContacts.ACCOUNT_TYPE);
222 if (cursor != null && accountTypeColumnIndex >= 0) {
223 if ((cursor.getColumnCount() > accountTypeColumnIndex)) {
224 final String accountType = cursor.getString(accountTypeColumnIndex);
225 return accountType != null
226 && accountType.equals(SimAccountType.ACCOUNT_TYPE);
227 }
228 }
229 return false;
230 }
231
Walter Janga84fe612016-01-13 16:49:04 -0800232 /**
233 * Returns the state of the search results currently presented to the user.
234 */
235 public SearchState createSearchState() {
236 return createSearchState(/* selectedPosition */ -1);
237 }
238
239 /**
240 * Returns the state of the search results presented to the user
241 * at the time the result in the given position was clicked.
242 */
243 public SearchState createSearchStateForSearchResultClick(int selectedPosition) {
244 return createSearchState(selectedPosition);
245 }
246
247 private SearchState createSearchState(int selectedPosition) {
248 final MultiSelectEntryContactListAdapter adapter = getAdapter();
249 if (adapter == null) {
250 return null;
251 }
252 final SearchState searchState = new SearchState();
253 searchState.queryLength = adapter.getQueryString() == null
254 ? 0 : adapter.getQueryString().length();
255 searchState.numPartitions = adapter.getPartitionCount();
256
257 // Set the number of results displayed to the user. Note that the adapter.getCount(),
258 // value does not always match the number of results actually displayed to the user,
259 // which is why we calculate it manually.
260 final List<Integer> numResultsInEachPartition = new ArrayList<>();
261 for (int i = 0; i < adapter.getPartitionCount(); i++) {
262 final Cursor cursor = adapter.getCursor(i);
263 if (cursor == null || cursor.isClosed()) {
264 // Something went wrong, abort.
265 numResultsInEachPartition.clear();
266 break;
267 }
268 numResultsInEachPartition.add(cursor.getCount());
269 }
270 if (!numResultsInEachPartition.isEmpty()) {
271 int numResults = 0;
272 for (int i = 0; i < numResultsInEachPartition.size(); i++) {
273 numResults += numResultsInEachPartition.get(i);
274 }
275 searchState.numResults = numResults;
276 }
277
278 // If a selection was made, set additional search state
279 if (selectedPosition >= 0) {
280 searchState.selectedPartition = adapter.getPartitionForPosition(selectedPosition);
281 searchState.selectedIndexInPartition = adapter.getOffsetInPartition(selectedPosition);
282 final Cursor cursor = adapter.getCursor(searchState.selectedPartition);
283 searchState.numResultsInSelectedPartition =
284 cursor == null || cursor.isClosed() ? -1 : cursor.getCount();
285
286 // Calculate the index across all partitions
287 if (!numResultsInEachPartition.isEmpty()) {
288 int selectedIndex = 0;
289 for (int i = 0; i < searchState.selectedPartition; i++) {
290 selectedIndex += numResultsInEachPartition.get(i);
291 }
292 selectedIndex += searchState.selectedIndexInPartition;
293 searchState.selectedIndex = selectedIndex;
294 }
295 }
296 return searchState;
297 }
Wenyi Wang1114fde2016-07-11 21:44:02 -0700298
Gary Mai967cffd2016-08-01 16:54:25 -0700299 protected void setLayoutAnimation(final ViewGroup view, int animationId) {
300 if (view == null) {
301 return;
302 }
303 view.setLayoutAnimationListener(new Animation.AnimationListener() {
304 @Override
305 public void onAnimationStart(Animation animation) {
306 }
307
308 @Override
309 public void onAnimationEnd(Animation animation) {
310 view.setLayoutAnimation(null);
311 }
312
313 @Override
314 public void onAnimationRepeat(Animation animation) {
315 }
316 });
317 view.setLayoutAnimation(AnimationUtils.loadLayoutAnimation(getActivity(), animationId));
318 }
319
Wenyi Wang1114fde2016-07-11 21:44:02 -0700320 @Override
321 public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
322 int totalItemCount) {
323 final View accountFilterContainer = getView().findViewById(
324 R.id.account_filter_header_container);
325 if (accountFilterContainer == null) {
326 return;
327 }
Wenyi Wang141b8372016-08-03 11:13:10 -0700328
329 int firstCompletelyVisibleItem = firstVisibleItem;
330 if (view != null && view.getChildAt(0) != null && view.getChildAt(0).getTop() < 0) {
331 firstCompletelyVisibleItem++;
332 }
333
334 if (firstCompletelyVisibleItem == 0) {
Wenyi Wang81067f52016-07-26 18:18:11 -0700335 ViewCompat.setElevation(accountFilterContainer, 0);
Wenyi Wang1114fde2016-07-11 21:44:02 -0700336 } else {
Wenyi Wang81067f52016-07-26 18:18:11 -0700337 ViewCompat.setElevation(accountFilterContainer,
338 getResources().getDimension(R.dimen.contact_list_header_elevation));
Wenyi Wang1114fde2016-07-11 21:44:02 -0700339 }
340 }
341
Walter Jang92942632016-07-14 19:49:32 +0000342 protected void bindListHeaderCustom(View listView, View accountFilterContainer) {
343 bindListHeaderCommon(listView, accountFilterContainer);
344
345 final TextView accountFilterHeader = (TextView) accountFilterContainer.findViewById(
346 R.id.account_filter_header);
347 accountFilterHeader.setText(R.string.listCustomView);
348 accountFilterHeader.setAllCaps(false);
349
350 final ImageView accountFilterHeaderIcon = (ImageView) accountFilterContainer
351 .findViewById(R.id.account_filter_icon);
Wenyi Wang20db9852016-07-18 18:41:41 -0700352 accountFilterHeaderIcon.setVisibility(View.GONE);
Walter Jang92942632016-07-14 19:49:32 +0000353 }
354
Wenyi Wang1114fde2016-07-11 21:44:02 -0700355 /**
356 * Show account icon, count of contacts and account name in the header of the list.
357 */
358 protected void bindListHeader(Context context, View listView, View accountFilterContainer,
359 AccountWithDataSet accountWithDataSet, int memberCount) {
360 if (memberCount < 0) {
361 hideHeaderAndAddPadding(context, listView, accountFilterContainer);
362 return;
363 }
364
Walter Jang92942632016-07-14 19:49:32 +0000365 bindListHeaderCommon(listView, accountFilterContainer);
Wenyi Wang1114fde2016-07-11 21:44:02 -0700366
Wenyi Wang96fb8b52016-11-07 14:12:11 -0800367 final AccountTypeManager accountTypeManager = AccountTypeManager.getInstance(context);
368 final AccountType accountType = accountTypeManager.getAccountType(
369 accountWithDataSet.type, accountWithDataSet.dataSet);
370
371 // Set text of count of contacts and account name
Wenyi Wang1114fde2016-07-11 21:44:02 -0700372 final TextView accountFilterHeader = (TextView) accountFilterContainer.findViewById(
373 R.id.account_filter_header);
Wenyi Wang96fb8b52016-11-07 14:12:11 -0800374 final String headerText = shouldShowAccountName(accountType)
Wenyi Wang3d8803e2016-07-18 14:29:37 -0700375 ? String.format(context.getResources().getQuantityString(
376 R.plurals.contacts_count_with_account, memberCount),
377 memberCount, accountWithDataSet.name)
378 : context.getResources().getQuantityString(
379 R.plurals.contacts_count, memberCount, memberCount);
380 accountFilterHeader.setText(headerText);
Wenyi Wang1114fde2016-07-11 21:44:02 -0700381 accountFilterHeader.setAllCaps(false);
382
383 // Set icon of the account
Wenyi Wang1114fde2016-07-11 21:44:02 -0700384 final Drawable icon = accountType != null ? accountType.getDisplayIcon(context) : null;
385 final ImageView accountFilterHeaderIcon = (ImageView) accountFilterContainer
386 .findViewById(R.id.account_filter_icon);
Wenyi Wang81067f52016-07-26 18:18:11 -0700387
388 // If it's a writable Google account, we set icon size as 24dp; otherwise, we set it as
389 // 20dp. And we need to change margin accordingly. This is because the Google icon looks
390 // smaller when the icons are of the same size.
391 if (accountType instanceof GoogleAccountType) {
392 accountFilterHeaderIcon.getLayoutParams().height = getResources()
393 .getDimensionPixelOffset(R.dimen.contact_browser_list_header_icon_size);
Wenyi Wang6c46e5b2016-11-17 10:57:42 -0800394 accountFilterHeaderIcon.getLayoutParams().width = getResources()
395 .getDimensionPixelOffset(R.dimen.contact_browser_list_header_icon_size);
Wenyi Wang81067f52016-07-26 18:18:11 -0700396
397 setMargins(accountFilterHeaderIcon,
398 getResources().getDimensionPixelOffset(
399 R.dimen.contact_browser_list_header_icon_left_margin),
400 getResources().getDimensionPixelOffset(
401 R.dimen.contact_browser_list_header_icon_right_margin));
402 } else {
403 accountFilterHeaderIcon.getLayoutParams().height = getResources()
404 .getDimensionPixelOffset(R.dimen.contact_browser_list_header_icon_size_alt);
Wenyi Wang6c46e5b2016-11-17 10:57:42 -0800405 accountFilterHeaderIcon.getLayoutParams().width = getResources()
406 .getDimensionPixelOffset(R.dimen.contact_browser_list_header_icon_size_alt);
Wenyi Wang81067f52016-07-26 18:18:11 -0700407
408 setMargins(accountFilterHeaderIcon,
409 getResources().getDimensionPixelOffset(
410 R.dimen.contact_browser_list_header_icon_left_margin_alt),
411 getResources().getDimensionPixelOffset(
412 R.dimen.contact_browser_list_header_icon_right_margin_alt));
413 }
414 accountFilterHeaderIcon.requestLayout();
415
Walter Jang92942632016-07-14 19:49:32 +0000416 accountFilterHeaderIcon.setVisibility(View.VISIBLE);
Wenyi Wang1114fde2016-07-11 21:44:02 -0700417 accountFilterHeaderIcon.setImageDrawable(icon);
418 }
419
Wenyi Wang96fb8b52016-11-07 14:12:11 -0800420 private boolean shouldShowAccountName(AccountType accountType) {
421 return (accountType.isGroupMembershipEditable() && this instanceof GroupMembersFragment)
422 || GoogleAccountType.ACCOUNT_TYPE.equals(accountType.accountType);
423 }
424
Wenyi Wang81067f52016-07-26 18:18:11 -0700425 private void setMargins(View v, int l, int r) {
426 if (v.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) {
427 ViewGroup.MarginLayoutParams p = (ViewGroup.MarginLayoutParams) v.getLayoutParams();
428 p.setMarginStart(l);
429 p.setMarginEnd(r);
430 v.setLayoutParams(p);
431 v.requestLayout();
432 }
433 }
434
Walter Jang92942632016-07-14 19:49:32 +0000435 private void bindListHeaderCommon(View listView, View accountFilterContainer) {
436 // Show header and remove top padding of the list
437 accountFilterContainer.setVisibility(View.VISIBLE);
Wenyi Wang7cd9af32016-07-17 16:00:43 -0700438 setListViewPaddingTop(listView, /* paddingTop */ 0);
Walter Jang92942632016-07-14 19:49:32 +0000439 }
440
Wenyi Wang1114fde2016-07-11 21:44:02 -0700441 /**
442 * Hide header of list view and add padding to the top of list view.
443 */
444 protected void hideHeaderAndAddPadding(Context context, View listView,
445 View accountFilterContainer) {
446 accountFilterContainer.setVisibility(View.GONE);
Wenyi Wang7cd9af32016-07-17 16:00:43 -0700447 setListViewPaddingTop(listView,
448 /* paddingTop */ context.getResources().getDimensionPixelSize(
449 R.dimen.contact_browser_list_item_padding_top_or_bottom));
450 }
451
452 private void setListViewPaddingTop(View listView, int paddingTop) {
453 listView.setPadding(listView.getPaddingLeft(), paddingTop, listView.getPaddingRight(),
454 listView.getPaddingBottom());
Wenyi Wang1114fde2016-07-11 21:44:02 -0700455 }
456
Wenyi Wang79675452016-08-17 10:43:28 -0700457 /**
458 * Returns the {@link ActionBarAdapter} object associated with list fragment.
459 */
460 public ActionBarAdapter getActionBarAdapter() {
461 return null;
462 }
Brian Attwell20510ec2015-02-27 16:10:45 -0800463}