blob: 7a6a64acc6711ba0614f05ff01909d2d7a07b9f0 [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;
24import android.support.v4.view.ViewCompat;
25import 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;
Walter Jange9ea4f02016-05-10 09:39:46 -070038import com.android.contacts.common.list.ContactEntryListFragment;
39import com.android.contacts.common.list.MultiSelectEntryContactListAdapter;
40import com.android.contacts.common.list.MultiSelectEntryContactListAdapter.SelectedContactsListener;
Wenyi Wang2b943992016-05-20 17:21:35 -070041import com.android.contacts.common.logging.ListEvent.ActionType;
Walter Jange9ea4f02016-05-10 09:39:46 -070042import com.android.contacts.common.logging.Logger;
Wenyi Wang2b943992016-05-20 17:21:35 -070043import com.android.contacts.common.logging.SearchState;
Wenyi Wang1114fde2016-07-11 21:44:02 -070044import com.android.contacts.common.model.AccountTypeManager;
45import com.android.contacts.common.model.account.AccountType;
46import com.android.contacts.common.model.account.AccountWithDataSet;
47import com.android.contacts.common.model.account.GoogleAccountType;
Wenyi Wang96fb8b52016-11-07 14:12:11 -080048import com.android.contacts.group.GroupMembersFragment;
Brian Attwell20510ec2015-02-27 16:10:45 -080049
Walter Janga84fe612016-01-13 16:49:04 -080050import java.util.ArrayList;
51import java.util.List;
Brian Attwell20510ec2015-02-27 16:10:45 -080052import java.util.TreeSet;
53
54/**
55 * Fragment containing a contact list used for browsing contacts and optionally selecting
56 * multiple contacts via checkboxes.
57 */
Walter Jange9ea4f02016-05-10 09:39:46 -070058public abstract class MultiSelectContactsListFragment<T extends MultiSelectEntryContactListAdapter>
59 extends ContactEntryListFragment<T>
Brian Attwell20510ec2015-02-27 16:10:45 -080060 implements SelectedContactsListener {
61
Gary Mai967cffd2016-08-01 16:54:25 -070062 protected boolean mAnimateOnLoad;
Walter Jang9c1fa5d2016-05-17 09:04:40 -070063 private static final String TAG = "MultiContactsList";
64
Brian Attwell20510ec2015-02-27 16:10:45 -080065 public interface OnCheckBoxListActionListener {
66 void onStartDisplayingCheckBoxes();
67 void onSelectedContactIdsChanged();
Brian Attwell8f8937f2015-03-05 14:07:43 -080068 void onStopDisplayingCheckBoxes();
Brian Attwell20510ec2015-02-27 16:10:45 -080069 }
70
71 private static final String EXTRA_KEY_SELECTED_CONTACTS = "selected_contacts";
72
Walter Janga84fe612016-01-13 16:49:04 -080073 private static final String KEY_SEARCH_RESULT_CLICKED = "search_result_clicked";
74
Brian Attwell20510ec2015-02-27 16:10:45 -080075 private OnCheckBoxListActionListener mCheckBoxListListener;
Walter Janga84fe612016-01-13 16:49:04 -080076 private boolean mSearchResultClicked;
Brian Attwell20510ec2015-02-27 16:10:45 -080077
78 public void setCheckBoxListListener(OnCheckBoxListActionListener checkBoxListListener) {
79 mCheckBoxListListener = checkBoxListListener;
80 }
81
Walter Janga84fe612016-01-13 16:49:04 -080082 /**
83 * Whether a search result was clicked by the user. Tracked so that we can distinguish
Walter Jang9c1fa5d2016-05-17 09:04:40 -070084 * between exiting the search mode after a result was clicked from exiting w/o clicking
Walter Janga84fe612016-01-13 16:49:04 -080085 * any search result.
86 */
87 public boolean wasSearchResultClicked() {
88 return mSearchResultClicked;
89 }
90
91 /**
92 * Resets whether a search result was clicked by the user to false.
93 */
94 public void resetSearchResultClicked() {
95 mSearchResultClicked = false;
96 }
97
Gary Mai967cffd2016-08-01 16:54:25 -070098 public void setAnimateOnLoad(boolean shouldAnimate) {
99 mAnimateOnLoad = shouldAnimate;
100 }
101
Brian Attwell20510ec2015-02-27 16:10:45 -0800102 @Override
103 public void onSelectedContactsChanged() {
Walter Jang9c1fa5d2016-05-17 09:04:40 -0700104 if (mCheckBoxListListener != null) mCheckBoxListListener.onSelectedContactIdsChanged();
Brian Attwell20510ec2015-02-27 16:10:45 -0800105 }
106
107 @Override
Gary Mai967cffd2016-08-01 16:54:25 -0700108 public View onCreateView(LayoutInflater inflater, ViewGroup container,
109 Bundle savedInstanceState) {
110 super.onCreateView(inflater, container, savedInstanceState);
111 if (savedInstanceState == null && mAnimateOnLoad) {
112 setLayoutAnimation(getListView(), R.anim.slide_and_fade_in_layout_animation);
113 }
114 return getView();
115 }
116
117 @Override
Brian Attwell20510ec2015-02-27 16:10:45 -0800118 public void onActivityCreated(Bundle savedInstanceState) {
119 super.onActivityCreated(savedInstanceState);
120 if (savedInstanceState != null) {
121 final TreeSet<Long> selectedContactIds = (TreeSet<Long>)
122 savedInstanceState.getSerializable(EXTRA_KEY_SELECTED_CONTACTS);
123 getAdapter().setSelectedContactIds(selectedContactIds);
Walter Janga84fe612016-01-13 16:49:04 -0800124 mSearchResultClicked = savedInstanceState.getBoolean(KEY_SEARCH_RESULT_CLICKED);
Brian Attwell20510ec2015-02-27 16:10:45 -0800125 }
126 }
127
Wenyi Wang6927bf32016-08-15 18:31:24 -0700128 @Override
129 public void onStart() {
130 super.onStart();
131 if (mCheckBoxListListener != null) {
132 mCheckBoxListListener.onSelectedContactIdsChanged();
133 }
134 }
135
Brian Attwell20510ec2015-02-27 16:10:45 -0800136 public TreeSet<Long> getSelectedContactIds() {
Walter Jang9c1fa5d2016-05-17 09:04:40 -0700137 return getAdapter().getSelectedContactIds();
138 }
139
140 public long[] getSelectedContactIdsArray() {
141 return getAdapter().getSelectedContactIdsArray();
Brian Attwell20510ec2015-02-27 16:10:45 -0800142 }
143
144 @Override
Brian Attwell20510ec2015-02-27 16:10:45 -0800145 protected void configureAdapter() {
146 super.configureAdapter();
147 getAdapter().setSelectedContactsListener(this);
148 }
149
150 @Override
151 public void onSaveInstanceState(Bundle outState) {
152 super.onSaveInstanceState(outState);
153 outState.putSerializable(EXTRA_KEY_SELECTED_CONTACTS, getSelectedContactIds());
Walter Janga84fe612016-01-13 16:49:04 -0800154 outState.putBoolean(KEY_SEARCH_RESULT_CLICKED, mSearchResultClicked);
Brian Attwell20510ec2015-02-27 16:10:45 -0800155 }
156
157 public void displayCheckBoxes(boolean displayCheckBoxes) {
Walter Jang9c1fa5d2016-05-17 09:04:40 -0700158 if (getAdapter() != null) {
159 getAdapter().setDisplayCheckBoxes(displayCheckBoxes);
160 if (!displayCheckBoxes) {
161 clearCheckBoxes();
162 }
Brian Attwell20510ec2015-02-27 16:10:45 -0800163 }
164 }
Brian Attwelld2962a32015-03-02 14:48:50 -0800165
166 public void clearCheckBoxes() {
167 getAdapter().setSelectedContactIds(new TreeSet<Long>());
168 }
169
Brian Attwell20510ec2015-02-27 16:10:45 -0800170 @Override
171 protected boolean onItemLongClick(int position, long id) {
Brian Attwell8f8937f2015-03-05 14:07:43 -0800172 final int previouslySelectedCount = getAdapter().getSelectedContactIds().size();
Walter Jang9c1fa5d2016-05-17 09:04:40 -0700173 final long contactId = getContactId(position);
Tingting Wang80dfab32015-07-29 14:42:40 -0700174 final int partition = getAdapter().getPartitionForPosition(position);
Walter Jang9c1fa5d2016-05-17 09:04:40 -0700175 if (contactId >= 0 && partition == ContactsContract.Directory.DEFAULT) {
176 if (mCheckBoxListListener != null) {
177 mCheckBoxListListener.onStartDisplayingCheckBoxes();
178 }
179 getAdapter().toggleSelectionOfContactId(contactId);
Wenyi Wang2b943992016-05-20 17:21:35 -0700180 Logger.logListEvent(ActionType.SELECT, getListType(),
181 /* count */ getAdapter().getCount(), /* clickedIndex */ position,
182 /* numSelected */ 1);
Walter Jang9c1fa5d2016-05-17 09:04:40 -0700183 // Manually send clicked event if there is a checkbox.
Wenyi Wang2b943992016-05-20 17:21:35 -0700184 // See b/24098561. TalkBack will not read it otherwise.
Walter Jang9c1fa5d2016-05-17 09:04:40 -0700185 final int index = position + getListView().getHeaderViewsCount() - getListView()
186 .getFirstVisiblePosition();
187 if (index >= 0 && index < getListView().getChildCount()) {
188 getListView().getChildAt(index).sendAccessibilityEvent(AccessibilityEvent
189 .TYPE_VIEW_CLICKED);
Brian Attwellc00112f2015-03-02 18:32:35 -0800190 }
Brian Attwell20510ec2015-02-27 16:10:45 -0800191 }
Brian Attwell8f8937f2015-03-05 14:07:43 -0800192 final int nowSelectedCount = getAdapter().getSelectedContactIds().size();
193 if (mCheckBoxListListener != null
194 && previouslySelectedCount != 0 && nowSelectedCount == 0) {
195 // Last checkbox has been unchecked. So we should stop displaying checkboxes.
196 mCheckBoxListListener.onStopDisplayingCheckBoxes();
197 }
Brian Attwell20510ec2015-02-27 16:10:45 -0800198 return true;
199 }
200
201 @Override
202 protected void onItemClick(int position, long id) {
Walter Jang9c1fa5d2016-05-17 09:04:40 -0700203 final long contactId = getContactId(position);
204 if (contactId < 0) {
Brian Attwell20510ec2015-02-27 16:10:45 -0800205 return;
206 }
207 if (getAdapter().isDisplayingCheckBoxes()) {
Walter Jang9c1fa5d2016-05-17 09:04:40 -0700208 getAdapter().toggleSelectionOfContactId(contactId);
Brian Attwell20510ec2015-02-27 16:10:45 -0800209 } else {
Walter Jang82c90332016-02-24 17:34:34 -0800210 if (isSearchMode()) {
211 mSearchResultClicked = true;
212 Logger.logSearchEvent(createSearchStateForSearchResultClick(position));
213 }
Brian Attwell20510ec2015-02-27 16:10:45 -0800214 }
Brian Attwell8f8937f2015-03-05 14:07:43 -0800215 if (mCheckBoxListListener != null && getAdapter().getSelectedContactIds().size() == 0) {
216 mCheckBoxListListener.onStopDisplayingCheckBoxes();
217 }
Brian Attwell20510ec2015-02-27 16:10:45 -0800218 }
219
Walter Jang9c1fa5d2016-05-17 09:04:40 -0700220 private long getContactId(int position) {
221 final int contactIdColumnIndex = getAdapter().getContactColumnIdIndex();
222
223 final Cursor cursor = (Cursor) getAdapter().getItem(position);
224 if (cursor != null) {
225 if (cursor.getColumnCount() > contactIdColumnIndex) {
226 return cursor.getLong(contactIdColumnIndex);
227 }
228 }
229
230 Log.w(TAG, "Failed to get contact ID from cursor column " + contactIdColumnIndex);
231 return -1;
232 }
233
Walter Janga84fe612016-01-13 16:49:04 -0800234 /**
235 * Returns the state of the search results currently presented to the user.
236 */
237 public SearchState createSearchState() {
238 return createSearchState(/* selectedPosition */ -1);
239 }
240
241 /**
242 * Returns the state of the search results presented to the user
243 * at the time the result in the given position was clicked.
244 */
245 public SearchState createSearchStateForSearchResultClick(int selectedPosition) {
246 return createSearchState(selectedPosition);
247 }
248
249 private SearchState createSearchState(int selectedPosition) {
250 final MultiSelectEntryContactListAdapter adapter = getAdapter();
251 if (adapter == null) {
252 return null;
253 }
254 final SearchState searchState = new SearchState();
255 searchState.queryLength = adapter.getQueryString() == null
256 ? 0 : adapter.getQueryString().length();
257 searchState.numPartitions = adapter.getPartitionCount();
258
259 // Set the number of results displayed to the user. Note that the adapter.getCount(),
260 // value does not always match the number of results actually displayed to the user,
261 // which is why we calculate it manually.
262 final List<Integer> numResultsInEachPartition = new ArrayList<>();
263 for (int i = 0; i < adapter.getPartitionCount(); i++) {
264 final Cursor cursor = adapter.getCursor(i);
265 if (cursor == null || cursor.isClosed()) {
266 // Something went wrong, abort.
267 numResultsInEachPartition.clear();
268 break;
269 }
270 numResultsInEachPartition.add(cursor.getCount());
271 }
272 if (!numResultsInEachPartition.isEmpty()) {
273 int numResults = 0;
274 for (int i = 0; i < numResultsInEachPartition.size(); i++) {
275 numResults += numResultsInEachPartition.get(i);
276 }
277 searchState.numResults = numResults;
278 }
279
280 // If a selection was made, set additional search state
281 if (selectedPosition >= 0) {
282 searchState.selectedPartition = adapter.getPartitionForPosition(selectedPosition);
283 searchState.selectedIndexInPartition = adapter.getOffsetInPartition(selectedPosition);
284 final Cursor cursor = adapter.getCursor(searchState.selectedPartition);
285 searchState.numResultsInSelectedPartition =
286 cursor == null || cursor.isClosed() ? -1 : cursor.getCount();
287
288 // Calculate the index across all partitions
289 if (!numResultsInEachPartition.isEmpty()) {
290 int selectedIndex = 0;
291 for (int i = 0; i < searchState.selectedPartition; i++) {
292 selectedIndex += numResultsInEachPartition.get(i);
293 }
294 selectedIndex += searchState.selectedIndexInPartition;
295 searchState.selectedIndex = selectedIndex;
296 }
297 }
298 return searchState;
299 }
Wenyi Wang1114fde2016-07-11 21:44:02 -0700300
Gary Mai967cffd2016-08-01 16:54:25 -0700301 protected void setLayoutAnimation(final ViewGroup view, int animationId) {
302 if (view == null) {
303 return;
304 }
305 view.setLayoutAnimationListener(new Animation.AnimationListener() {
306 @Override
307 public void onAnimationStart(Animation animation) {
308 }
309
310 @Override
311 public void onAnimationEnd(Animation animation) {
312 view.setLayoutAnimation(null);
313 }
314
315 @Override
316 public void onAnimationRepeat(Animation animation) {
317 }
318 });
319 view.setLayoutAnimation(AnimationUtils.loadLayoutAnimation(getActivity(), animationId));
320 }
321
Wenyi Wang1114fde2016-07-11 21:44:02 -0700322 @Override
323 public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
324 int totalItemCount) {
325 final View accountFilterContainer = getView().findViewById(
326 R.id.account_filter_header_container);
327 if (accountFilterContainer == null) {
328 return;
329 }
Wenyi Wang141b8372016-08-03 11:13:10 -0700330
331 int firstCompletelyVisibleItem = firstVisibleItem;
332 if (view != null && view.getChildAt(0) != null && view.getChildAt(0).getTop() < 0) {
333 firstCompletelyVisibleItem++;
334 }
335
336 if (firstCompletelyVisibleItem == 0) {
Wenyi Wang81067f52016-07-26 18:18:11 -0700337 ViewCompat.setElevation(accountFilterContainer, 0);
Wenyi Wang1114fde2016-07-11 21:44:02 -0700338 } else {
Wenyi Wang81067f52016-07-26 18:18:11 -0700339 ViewCompat.setElevation(accountFilterContainer,
340 getResources().getDimension(R.dimen.contact_list_header_elevation));
Wenyi Wang1114fde2016-07-11 21:44:02 -0700341 }
342 }
343
Walter Jang92942632016-07-14 19:49:32 +0000344 protected void bindListHeaderCustom(View listView, View accountFilterContainer) {
345 bindListHeaderCommon(listView, accountFilterContainer);
346
347 final TextView accountFilterHeader = (TextView) accountFilterContainer.findViewById(
348 R.id.account_filter_header);
349 accountFilterHeader.setText(R.string.listCustomView);
350 accountFilterHeader.setAllCaps(false);
351
352 final ImageView accountFilterHeaderIcon = (ImageView) accountFilterContainer
353 .findViewById(R.id.account_filter_icon);
Wenyi Wang20db9852016-07-18 18:41:41 -0700354 accountFilterHeaderIcon.setVisibility(View.GONE);
Walter Jang92942632016-07-14 19:49:32 +0000355 }
356
Wenyi Wang1114fde2016-07-11 21:44:02 -0700357 /**
358 * Show account icon, count of contacts and account name in the header of the list.
359 */
360 protected void bindListHeader(Context context, View listView, View accountFilterContainer,
361 AccountWithDataSet accountWithDataSet, int memberCount) {
362 if (memberCount < 0) {
363 hideHeaderAndAddPadding(context, listView, accountFilterContainer);
364 return;
365 }
366
Walter Jang92942632016-07-14 19:49:32 +0000367 bindListHeaderCommon(listView, accountFilterContainer);
Wenyi Wang1114fde2016-07-11 21:44:02 -0700368
Wenyi Wang96fb8b52016-11-07 14:12:11 -0800369 final AccountTypeManager accountTypeManager = AccountTypeManager.getInstance(context);
370 final AccountType accountType = accountTypeManager.getAccountType(
371 accountWithDataSet.type, accountWithDataSet.dataSet);
372
373 // Set text of count of contacts and account name
Wenyi Wang1114fde2016-07-11 21:44:02 -0700374 final TextView accountFilterHeader = (TextView) accountFilterContainer.findViewById(
375 R.id.account_filter_header);
Wenyi Wang96fb8b52016-11-07 14:12:11 -0800376 final String headerText = shouldShowAccountName(accountType)
Wenyi Wang3d8803e2016-07-18 14:29:37 -0700377 ? String.format(context.getResources().getQuantityString(
378 R.plurals.contacts_count_with_account, memberCount),
379 memberCount, accountWithDataSet.name)
380 : context.getResources().getQuantityString(
381 R.plurals.contacts_count, memberCount, memberCount);
382 accountFilterHeader.setText(headerText);
Wenyi Wang1114fde2016-07-11 21:44:02 -0700383 accountFilterHeader.setAllCaps(false);
384
385 // Set icon of the account
Wenyi Wang1114fde2016-07-11 21:44:02 -0700386 final Drawable icon = accountType != null ? accountType.getDisplayIcon(context) : null;
387 final ImageView accountFilterHeaderIcon = (ImageView) accountFilterContainer
388 .findViewById(R.id.account_filter_icon);
Wenyi Wang81067f52016-07-26 18:18:11 -0700389
390 // If it's a writable Google account, we set icon size as 24dp; otherwise, we set it as
391 // 20dp. And we need to change margin accordingly. This is because the Google icon looks
392 // smaller when the icons are of the same size.
393 if (accountType instanceof GoogleAccountType) {
394 accountFilterHeaderIcon.getLayoutParams().height = getResources()
395 .getDimensionPixelOffset(R.dimen.contact_browser_list_header_icon_size);
Wenyi Wang6c46e5b2016-11-17 10:57:42 -0800396 accountFilterHeaderIcon.getLayoutParams().width = getResources()
397 .getDimensionPixelOffset(R.dimen.contact_browser_list_header_icon_size);
Wenyi Wang81067f52016-07-26 18:18:11 -0700398
399 setMargins(accountFilterHeaderIcon,
400 getResources().getDimensionPixelOffset(
401 R.dimen.contact_browser_list_header_icon_left_margin),
402 getResources().getDimensionPixelOffset(
403 R.dimen.contact_browser_list_header_icon_right_margin));
404 } else {
405 accountFilterHeaderIcon.getLayoutParams().height = getResources()
406 .getDimensionPixelOffset(R.dimen.contact_browser_list_header_icon_size_alt);
Wenyi Wang6c46e5b2016-11-17 10:57:42 -0800407 accountFilterHeaderIcon.getLayoutParams().width = getResources()
408 .getDimensionPixelOffset(R.dimen.contact_browser_list_header_icon_size_alt);
Wenyi Wang81067f52016-07-26 18:18:11 -0700409
410 setMargins(accountFilterHeaderIcon,
411 getResources().getDimensionPixelOffset(
412 R.dimen.contact_browser_list_header_icon_left_margin_alt),
413 getResources().getDimensionPixelOffset(
414 R.dimen.contact_browser_list_header_icon_right_margin_alt));
415 }
416 accountFilterHeaderIcon.requestLayout();
417
Walter Jang92942632016-07-14 19:49:32 +0000418 accountFilterHeaderIcon.setVisibility(View.VISIBLE);
Wenyi Wang1114fde2016-07-11 21:44:02 -0700419 accountFilterHeaderIcon.setImageDrawable(icon);
420 }
421
Wenyi Wang96fb8b52016-11-07 14:12:11 -0800422 private boolean shouldShowAccountName(AccountType accountType) {
423 return (accountType.isGroupMembershipEditable() && this instanceof GroupMembersFragment)
424 || GoogleAccountType.ACCOUNT_TYPE.equals(accountType.accountType);
425 }
426
Wenyi Wang81067f52016-07-26 18:18:11 -0700427 private void setMargins(View v, int l, int r) {
428 if (v.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) {
429 ViewGroup.MarginLayoutParams p = (ViewGroup.MarginLayoutParams) v.getLayoutParams();
430 p.setMarginStart(l);
431 p.setMarginEnd(r);
432 v.setLayoutParams(p);
433 v.requestLayout();
434 }
435 }
436
Walter Jang92942632016-07-14 19:49:32 +0000437 private void bindListHeaderCommon(View listView, View accountFilterContainer) {
438 // Show header and remove top padding of the list
439 accountFilterContainer.setVisibility(View.VISIBLE);
Wenyi Wang7cd9af32016-07-17 16:00:43 -0700440 setListViewPaddingTop(listView, /* paddingTop */ 0);
Walter Jang92942632016-07-14 19:49:32 +0000441 }
442
Wenyi Wang1114fde2016-07-11 21:44:02 -0700443 /**
444 * Hide header of list view and add padding to the top of list view.
445 */
446 protected void hideHeaderAndAddPadding(Context context, View listView,
447 View accountFilterContainer) {
448 accountFilterContainer.setVisibility(View.GONE);
Wenyi Wang7cd9af32016-07-17 16:00:43 -0700449 setListViewPaddingTop(listView,
450 /* paddingTop */ context.getResources().getDimensionPixelSize(
451 R.dimen.contact_browser_list_item_padding_top_or_bottom));
452 }
453
454 private void setListViewPaddingTop(View listView, int paddingTop) {
455 listView.setPadding(listView.getPaddingLeft(), paddingTop, listView.getPaddingRight(),
456 listView.getPaddingBottom());
Wenyi Wang1114fde2016-07-11 21:44:02 -0700457 }
458
Wenyi Wang79675452016-08-17 10:43:28 -0700459 /**
460 * Returns the {@link ActionBarAdapter} object associated with list fragment.
461 */
462 public ActionBarAdapter getActionBarAdapter() {
463 return null;
464 }
Brian Attwell20510ec2015-02-27 16:10:45 -0800465}