16b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee/* 2dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * Copyright (C) 2013 The Android Open Source Project 36b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee * 46b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee * Licensed under the Apache License, Version 2.0 (the "License"); 56b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee * you may not use this file except in compliance with the License. 66b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee * You may obtain a copy of the License at 76b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee * 86b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee * http://www.apache.org/licenses/LICENSE-2.0 96b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee * 106b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee * Unless required by applicable law or agreed to in writing, software 116b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee * distributed under the License is distributed on an "AS IS" BASIS, 126b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee * See the License for the specific language governing permissions and 146b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee * limitations under the License. 156b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee */ 166b049128c51b90e17ae14856d98130a22d3a5433Yorke Leepackage com.android.dialer.list; 176b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee 1838019af70eb1ca084d36291390bbc54dc81027deYorke Leeimport static android.Manifest.permission.READ_CONTACTS; 1938019af70eb1ca084d36291390bbc54dc81027deYorke Lee 205b2e21098d84e94fd629e5e07c3bbb66bf9b5d95Hongwei Wangimport android.animation.Animator; 215b2e21098d84e94fd629e5e07c3bbb66bf9b5d95Hongwei Wangimport android.animation.AnimatorSet; 225b2e21098d84e94fd629e5e07c3bbb66bf9b5d95Hongwei Wangimport android.animation.ObjectAnimator; 236b049128c51b90e17ae14856d98130a22d3a5433Yorke Leeimport android.app.Activity; 24beab3bbc2c977a48e3affc3e61cc2fdbb22c4ae2Brian Attwellimport android.app.Fragment; 256b049128c51b90e17ae14856d98130a22d3a5433Yorke Leeimport android.app.LoaderManager; 266b049128c51b90e17ae14856d98130a22d3a5433Yorke Leeimport android.content.CursorLoader; 276b049128c51b90e17ae14856d98130a22d3a5433Yorke Leeimport android.content.Loader; 287e1a68556c419c4b9b1eda9247e80262615fa809Yorke Leeimport android.content.pm.PackageManager; 296b049128c51b90e17ae14856d98130a22d3a5433Yorke Leeimport android.database.Cursor; 306b049128c51b90e17ae14856d98130a22d3a5433Yorke Leeimport android.graphics.Rect; 316b049128c51b90e17ae14856d98130a22d3a5433Yorke Leeimport android.net.Uri; 326b049128c51b90e17ae14856d98130a22d3a5433Yorke Leeimport android.os.Bundle; 33f5554ceb3c152949b4b6278b7f5e1522148a574cYorke Leeimport android.os.Trace; 346b049128c51b90e17ae14856d98130a22d3a5433Yorke Leeimport android.util.Log; 356b049128c51b90e17ae14856d98130a22d3a5433Yorke Leeimport android.view.LayoutInflater; 366b049128c51b90e17ae14856d98130a22d3a5433Yorke Leeimport android.view.View; 376b049128c51b90e17ae14856d98130a22d3a5433Yorke Leeimport android.view.ViewGroup; 38765734c1d602c9a6d166d653b3684e6408b771c4Yorke Leeimport android.view.ViewTreeObserver; 399b08f53ac993cffa249b73d3a2cc9ed5a9e71158Yorke Leeimport android.view.animation.AnimationUtils; 409b08f53ac993cffa249b73d3a2cc9ed5a9e71158Yorke Leeimport android.view.animation.LayoutAnimationController; 416b049128c51b90e17ae14856d98130a22d3a5433Yorke Leeimport android.widget.AbsListView; 426b049128c51b90e17ae14856d98130a22d3a5433Yorke Leeimport android.widget.AdapterView; 436b049128c51b90e17ae14856d98130a22d3a5433Yorke Leeimport android.widget.AdapterView.OnItemClickListener; 44ae6302b51b1f03ddd4865539b071ba2a661b977fYorke Leeimport android.widget.FrameLayout; 45ae6302b51b1f03ddd4865539b071ba2a661b977fYorke Leeimport android.widget.FrameLayout.LayoutParams; 464911300ae3fa7ab186ee271f8bc431b65a819a3cHongwei Wangimport android.widget.ImageView; 476b049128c51b90e17ae14856d98130a22d3a5433Yorke Leeimport android.widget.ListView; 486b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee 496b049128c51b90e17ae14856d98130a22d3a5433Yorke Leeimport com.android.contacts.common.ContactPhotoManager; 506b049128c51b90e17ae14856d98130a22d3a5433Yorke Leeimport com.android.contacts.common.ContactTileLoaderFactory; 516b049128c51b90e17ae14856d98130a22d3a5433Yorke Leeimport com.android.contacts.common.list.ContactTileView; 52e00c9fe163d19ee380b922e3fcbe736216d78cccYorke Leeimport com.android.contacts.common.list.OnPhoneNumberPickerActionListener; 53c16ea5ad67bf454158b364dec2f26c95a879c350Yorke Leeimport com.android.contacts.common.util.PermissionsUtil; 546b049128c51b90e17ae14856d98130a22d3a5433Yorke Leeimport com.android.dialer.R; 550a4327e6bfeedc23ddefb4df9f6e8041ebc87b59Andrew Leeimport com.android.dialer.util.DialerUtils; 5638019af70eb1ca084d36291390bbc54dc81027deYorke Leeimport com.android.dialer.widget.EmptyContentView; 57c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee 58c36684277aa45085999284bfe71cb8be71b3a464Yorke Leeimport java.util.ArrayList; 59c36684277aa45085999284bfe71cb8be71b3a464Yorke Leeimport java.util.HashMap; 606b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee 616b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee/** 62d999b71452baebec789f6f58f1955d30e834826dYorke Lee * This fragment displays the user's favorite/frequent contacts in a grid. 636b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee */ 64beab3bbc2c977a48e3affc3e61cc2fdbb22c4ae2Brian Attwellpublic class SpeedDialFragment extends Fragment implements OnItemClickListener, 6538019af70eb1ca084d36291390bbc54dc81027deYorke Lee PhoneFavoritesTileAdapter.OnDataSetChangedForAnimationListener, 6638019af70eb1ca084d36291390bbc54dc81027deYorke Lee EmptyContentView.OnEmptyViewActionButtonClickedListener { 67c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee 687e1a68556c419c4b9b1eda9247e80262615fa809Yorke Lee private static final int READ_CONTACTS_PERMISSION_REQUEST_CODE = 1; 697e1a68556c419c4b9b1eda9247e80262615fa809Yorke Lee 704ed7db87e6c0e71b2f656e77de938f3579bc36bfYorke Lee /** 714ed7db87e6c0e71b2f656e77de938f3579bc36bfYorke Lee * By default, the animation code assumes that all items in a list view are of the same height 724ed7db87e6c0e71b2f656e77de938f3579bc36bfYorke Lee * when animating new list items into view (e.g. from the bottom of the screen into view). 734ed7db87e6c0e71b2f656e77de938f3579bc36bfYorke Lee * This can cause incorrect translation offsets when a item that is larger or smaller than 744ed7db87e6c0e71b2f656e77de938f3579bc36bfYorke Lee * other list item is removed from the list. This key is used to provide the actual height 754ed7db87e6c0e71b2f656e77de938f3579bc36bfYorke Lee * of the removed object so that the actual translation appears correct to the user. 764ed7db87e6c0e71b2f656e77de938f3579bc36bfYorke Lee */ 774ed7db87e6c0e71b2f656e77de938f3579bc36bfYorke Lee private static final long KEY_REMOVED_ITEM_HEIGHT = Long.MAX_VALUE; 784ed7db87e6c0e71b2f656e77de938f3579bc36bfYorke Lee 79f5554ceb3c152949b4b6278b7f5e1522148a574cYorke Lee private static final String TAG = "SpeedDialFragment"; 803ed80a357d780310777178ad589d7771d4f7bf2dYorke Lee private static final boolean DEBUG = false; 81c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee 824911300ae3fa7ab186ee271f8bc431b65a819a3cHongwei Wang private int mAnimationDuration; 836b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee 846b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee /** 856b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee * Used with LoaderManager. 866b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee */ 876b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee private static int LOADER_ID_CONTACT_TILE = 1; 8821299c354c4178dd8f89eef42872cbd62cd4aaf0Yorke Lee 893cefcc69c10ab12bd782a0b53779dbd1cc0e2aa1Yorke Lee public interface HostInterface { 903cefcc69c10ab12bd782a0b53779dbd1cc0e2aa1Yorke Lee public void setDragDropController(DragDropController controller); 9138019af70eb1ca084d36291390bbc54dc81027deYorke Lee public void showAllContactsTab(); 923cefcc69c10ab12bd782a0b53779dbd1cc0e2aa1Yorke Lee } 933cefcc69c10ab12bd782a0b53779dbd1cc0e2aa1Yorke Lee 946b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee private class ContactTileLoaderListener implements LoaderManager.LoaderCallbacks<Cursor> { 956b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee @Override 966b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee public CursorLoader onCreateLoader(int id, Bundle args) { 976b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee if (DEBUG) Log.d(TAG, "ContactTileLoaderListener#onCreateLoader."); 986b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee return ContactTileLoaderFactory.createStrequentPhoneOnlyLoader(getActivity()); 996b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee } 1006b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee 1016b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee @Override 1026b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee public void onLoadFinished(Loader<Cursor> loader, Cursor data) { 1036b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee if (DEBUG) Log.d(TAG, "ContactTileLoaderListener#onLoadFinished"); 1046b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee mContactTileAdapter.setContactCursor(data); 1054fdf594962b3928c6497b471dbb1ee7be56e18efChristine Chen setEmptyViewVisibility(mContactTileAdapter.getCount() == 0); 1066b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee } 1076b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee 1086b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee @Override 1096b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee public void onLoaderReset(Loader<Cursor> loader) { 1106b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee if (DEBUG) Log.d(TAG, "ContactTileLoaderListener#onLoaderReset. "); 1116b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee } 1126b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee } 1136b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee 1146b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee private class ContactTileAdapterListener implements ContactTileView.Listener { 1156b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee @Override 1166b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee public void onContactSelected(Uri contactUri, Rect targetRect) { 117e00c9fe163d19ee380b922e3fcbe736216d78cccYorke Lee if (mPhoneNumberPickerActionListener != null) { 118e00c9fe163d19ee380b922e3fcbe736216d78cccYorke Lee mPhoneNumberPickerActionListener.onPickPhoneNumberAction(contactUri); 1196b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee } 1206b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee } 1216b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee 1226b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee @Override 1236b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee public void onCallNumberDirectly(String phoneNumber) { 124e00c9fe163d19ee380b922e3fcbe736216d78cccYorke Lee if (mPhoneNumberPickerActionListener != null) { 125e00c9fe163d19ee380b922e3fcbe736216d78cccYorke Lee mPhoneNumberPickerActionListener.onCallNumberDirectly(phoneNumber); 1266b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee } 1276b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee } 1286b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee 1296b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee @Override 1306b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee public int getApproximateTileWidth() { 131efb2d9c2e32ca4ed434ff785c4b3d18c9e08db6dYorke Lee return getView().getWidth(); 1326b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee } 1336b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee } 1346b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee 1356b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee private class ScrollListener implements ListView.OnScrollListener { 1366b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee @Override 1376b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee public void onScroll(AbsListView view, 1386b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee int firstVisibleItem, int visibleItemCount, int totalItemCount) { 13986e21f733049560e77b92f17a58474312d72ec3eYorke Lee if (mActivityScrollListener != null) { 14086e21f733049560e77b92f17a58474312d72ec3eYorke Lee mActivityScrollListener.onListFragmentScroll(firstVisibleItem, visibleItemCount, 14186e21f733049560e77b92f17a58474312d72ec3eYorke Lee totalItemCount); 14286e21f733049560e77b92f17a58474312d72ec3eYorke Lee } 1436b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee } 1446b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee 1456b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee @Override 1466b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee public void onScrollStateChanged(AbsListView view, int scrollState) { 147dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mActivityScrollListener.onListFragmentScrollStateChange(scrollState); 1486b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee } 1496b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee } 1506b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee 151e00c9fe163d19ee380b922e3fcbe736216d78cccYorke Lee private OnPhoneNumberPickerActionListener mPhoneNumberPickerActionListener; 152dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 153dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee private OnListFragmentScrolledListener mActivityScrollListener; 154dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee private PhoneFavoritesTileAdapter mContactTileAdapter; 1556b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee 1564fdf594962b3928c6497b471dbb1ee7be56e18efChristine Chen private View mParentView; 1574fdf594962b3928c6497b471dbb1ee7be56e18efChristine Chen 158bf5b298b1a5752a56315131a22434185198370a8Hongwei Wang private PhoneFavoriteListView mListView; 15918e7fdd55f67e3636c161462cb54e7f5555a04deYorke Lee 1603eb8ab2ab09a9e742cde17e36381a6dde058c4beYorke Lee private View mContactTileFrame; 1616b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee 162c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee private final HashMap<Long, Integer> mItemIdTopMap = new HashMap<Long, Integer>(); 163c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee private final HashMap<Long, Integer> mItemIdLeftMap = new HashMap<Long, Integer>(); 164c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee 1656b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee /** 16618e7fdd55f67e3636c161462cb54e7f5555a04deYorke Lee * Layout used when there are no favorites. 1676b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee */ 16838019af70eb1ca084d36291390bbc54dc81027deYorke Lee private EmptyContentView mEmptyView; 1696b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee 1706b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee private final ContactTileView.Listener mContactTileAdapterListener = 1716b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee new ContactTileAdapterListener(); 1726b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee private final LoaderManager.LoaderCallbacks<Cursor> mContactTileLoaderListener = 1736b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee new ContactTileLoaderListener(); 1746b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee private final ScrollListener mScrollListener = new ScrollListener(); 1756b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee 1766b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee @Override 1776b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee public void onAttach(Activity activity) { 1786b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee if (DEBUG) Log.d(TAG, "onAttach()"); 1796b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee super.onAttach(activity); 1806b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee 1816b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee // Construct two base adapters which will become part of PhoneFavoriteMergedAdapter. 1826b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee // We don't construct the resultant adapter at this moment since it requires LayoutInflater 1836b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee // that will be available on onCreateView(). 184dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mContactTileAdapter = new PhoneFavoritesTileAdapter(activity, mContactTileAdapterListener, 185efb2d9c2e32ca4ed434ff785c4b3d18c9e08db6dYorke Lee this); 1866b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee mContactTileAdapter.setPhotoLoader(ContactPhotoManager.getInstance(activity)); 1876b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee } 1886b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee 1896b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee @Override 1906b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee public void onCreate(Bundle savedState) { 1916b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee if (DEBUG) Log.d(TAG, "onCreate()"); 192f5554ceb3c152949b4b6278b7f5e1522148a574cYorke Lee Trace.beginSection(TAG + " onCreate"); 1936b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee super.onCreate(savedState); 1946b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee 1954911300ae3fa7ab186ee271f8bc431b65a819a3cHongwei Wang mAnimationDuration = getResources().getInteger(R.integer.fade_duration); 196f5554ceb3c152949b4b6278b7f5e1522148a574cYorke Lee Trace.endSection(); 1976b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee } 1986b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee 1996b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee @Override 200dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee public void onResume() { 201f5554ceb3c152949b4b6278b7f5e1522148a574cYorke Lee Trace.beginSection(TAG + " onResume"); 202dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee super.onResume(); 20321299c354c4178dd8f89eef42872cbd62cd4aaf0Yorke Lee 204c16ea5ad67bf454158b364dec2f26c95a879c350Yorke Lee if (PermissionsUtil.hasContactsPermissions(getActivity())) { 2052a613022dbb278f0f7dd94cf49885cde9d36100cYorke Lee if (getLoaderManager().getLoader(LOADER_ID_CONTACT_TILE) == null) { 2062a613022dbb278f0f7dd94cf49885cde9d36100cYorke Lee getLoaderManager().initLoader(LOADER_ID_CONTACT_TILE, null, 2072a613022dbb278f0f7dd94cf49885cde9d36100cYorke Lee mContactTileLoaderListener); 20838019af70eb1ca084d36291390bbc54dc81027deYorke Lee 2092a613022dbb278f0f7dd94cf49885cde9d36100cYorke Lee } else { 2102a613022dbb278f0f7dd94cf49885cde9d36100cYorke Lee getLoaderManager().getLoader(LOADER_ID_CONTACT_TILE).forceLoad(); 2112a613022dbb278f0f7dd94cf49885cde9d36100cYorke Lee } 21238019af70eb1ca084d36291390bbc54dc81027deYorke Lee 21338019af70eb1ca084d36291390bbc54dc81027deYorke Lee mEmptyView.setDescription(R.string.speed_dial_empty); 21438019af70eb1ca084d36291390bbc54dc81027deYorke Lee mEmptyView.setActionLabel(R.string.speed_dial_empty_add_favorite_action); 21538019af70eb1ca084d36291390bbc54dc81027deYorke Lee } else { 21638019af70eb1ca084d36291390bbc54dc81027deYorke Lee mEmptyView.setDescription(R.string.permission_no_speeddial); 21738019af70eb1ca084d36291390bbc54dc81027deYorke Lee mEmptyView.setActionLabel(R.string.permission_single_turn_on); 218c16ea5ad67bf454158b364dec2f26c95a879c350Yorke Lee } 219f5554ceb3c152949b4b6278b7f5e1522148a574cYorke Lee Trace.endSection(); 2206b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee } 2216b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee 2226b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee @Override 2236b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee public View onCreateView(LayoutInflater inflater, ViewGroup container, 2246b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee Bundle savedInstanceState) { 225f5554ceb3c152949b4b6278b7f5e1522148a574cYorke Lee Trace.beginSection(TAG + " onCreateView"); 22639f773e8a64ec1b770b2679871b7c44cac7243d2Andrew Lee mParentView = inflater.inflate(R.layout.speed_dial_fragment, container, false); 2276b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee 2284fdf594962b3928c6497b471dbb1ee7be56e18efChristine Chen mListView = (PhoneFavoriteListView) mParentView.findViewById(R.id.contact_tile_list); 2296b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee mListView.setOnItemClickListener(this); 2306b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee mListView.setVerticalScrollBarEnabled(false); 2316b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee mListView.setVerticalScrollbarPosition(View.SCROLLBAR_POSITION_RIGHT); 2326b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee mListView.setScrollBarStyle(ListView.SCROLLBARS_OUTSIDE_OVERLAY); 2333cefcc69c10ab12bd782a0b53779dbd1cc0e2aa1Yorke Lee mListView.getDragDropController().addOnDragDropListener(mContactTileAdapter); 2346b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee 2354911300ae3fa7ab186ee271f8bc431b65a819a3cHongwei Wang final ImageView dragShadowOverlay = 236f66cc0403faab0a31ccdb2c78e0dad5be11218f5Yorke Lee (ImageView) getActivity().findViewById(R.id.contact_tile_drag_shadow_overlay); 2374911300ae3fa7ab186ee271f8bc431b65a819a3cHongwei Wang mListView.setDragShadowOverlay(dragShadowOverlay); 2384911300ae3fa7ab186ee271f8bc431b65a819a3cHongwei Wang 23938019af70eb1ca084d36291390bbc54dc81027deYorke Lee mEmptyView = (EmptyContentView) mParentView.findViewById(R.id.empty_list_view); 24038019af70eb1ca084d36291390bbc54dc81027deYorke Lee mEmptyView.setImage(R.drawable.empty_speed_dial); 24138019af70eb1ca084d36291390bbc54dc81027deYorke Lee mEmptyView.setActionClickedListener(this); 2424fdf594962b3928c6497b471dbb1ee7be56e18efChristine Chen 2433eb8ab2ab09a9e742cde17e36381a6dde058c4beYorke Lee mContactTileFrame = mParentView.findViewById(R.id.contact_tile_frame); 2443eb8ab2ab09a9e742cde17e36381a6dde058c4beYorke Lee 2459b08f53ac993cffa249b73d3a2cc9ed5a9e71158Yorke Lee final LayoutAnimationController controller = new LayoutAnimationController( 2469b08f53ac993cffa249b73d3a2cc9ed5a9e71158Yorke Lee AnimationUtils.loadAnimation(getActivity(), android.R.anim.fade_in)); 2479b08f53ac993cffa249b73d3a2cc9ed5a9e71158Yorke Lee controller.setDelay(0); 2489b08f53ac993cffa249b73d3a2cc9ed5a9e71158Yorke Lee mListView.setLayoutAnimation(controller); 249efb2d9c2e32ca4ed434ff785c4b3d18c9e08db6dYorke Lee mListView.setAdapter(mContactTileAdapter); 2506b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee 2516b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee mListView.setOnScrollListener(mScrollListener); 2526b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee mListView.setFastScrollEnabled(false); 2536b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee mListView.setFastScrollAlwaysVisible(false); 254f5554ceb3c152949b4b6278b7f5e1522148a574cYorke Lee Trace.endSection(); 2554fdf594962b3928c6497b471dbb1ee7be56e18efChristine Chen return mParentView; 2566b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee } 2576b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee 258f420a5344995b2c450379159f679809690bc9880Yorke Lee public boolean hasFrequents() { 259f420a5344995b2c450379159f679809690bc9880Yorke Lee if (mContactTileAdapter == null) return false; 2606b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee return mContactTileAdapter.getNumFrequents() > 0; 2616b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee } 2626b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee 2634fdf594962b3928c6497b471dbb1ee7be56e18efChristine Chen /* package */ void setEmptyViewVisibility(final boolean visible) { 2644fdf594962b3928c6497b471dbb1ee7be56e18efChristine Chen final int previousVisibility = mEmptyView.getVisibility(); 2650bbd606a3d1da11a38fdc127f4067b06f71174f8Ihab Awad final int emptyViewVisibility = visible ? View.VISIBLE : View.GONE; 2660bbd606a3d1da11a38fdc127f4067b06f71174f8Ihab Awad final int listViewVisibility = visible ? View.GONE : View.VISIBLE; 2674fdf594962b3928c6497b471dbb1ee7be56e18efChristine Chen 2680bbd606a3d1da11a38fdc127f4067b06f71174f8Ihab Awad if (previousVisibility != emptyViewVisibility) { 269ae6302b51b1f03ddd4865539b071ba2a661b977fYorke Lee final FrameLayout.LayoutParams params = (LayoutParams) mContactTileFrame 2703eb8ab2ab09a9e742cde17e36381a6dde058c4beYorke Lee .getLayoutParams(); 2713eb8ab2ab09a9e742cde17e36381a6dde058c4beYorke Lee params.height = visible ? LayoutParams.WRAP_CONTENT : LayoutParams.MATCH_PARENT; 2723eb8ab2ab09a9e742cde17e36381a6dde058c4beYorke Lee mContactTileFrame.setLayoutParams(params); 2730bbd606a3d1da11a38fdc127f4067b06f71174f8Ihab Awad mEmptyView.setVisibility(emptyViewVisibility); 2740bbd606a3d1da11a38fdc127f4067b06f71174f8Ihab Awad mListView.setVisibility(listViewVisibility); 2754fdf594962b3928c6497b471dbb1ee7be56e18efChristine Chen } 2764fdf594962b3928c6497b471dbb1ee7be56e18efChristine Chen } 2774fdf594962b3928c6497b471dbb1ee7be56e18efChristine Chen 2786b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee @Override 2796b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee public void onStart() { 2806b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee super.onStart(); 2816b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee 282dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee final Activity activity = getActivity(); 283dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 284dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee try { 285dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mActivityScrollListener = (OnListFragmentScrolledListener) activity; 286dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } catch (ClassCastException e) { 287dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee throw new ClassCastException(activity.toString() 288dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee + " must implement OnListFragmentScrolledListener"); 289dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 2906b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee 2918dd6200bef2eb07486f4c7e288941cfcfed35e79Yorke Lee try { 2923cefcc69c10ab12bd782a0b53779dbd1cc0e2aa1Yorke Lee OnDragDropListener listener = (OnDragDropListener) activity; 2933cefcc69c10ab12bd782a0b53779dbd1cc0e2aa1Yorke Lee mListView.getDragDropController().addOnDragDropListener(listener); 2943cefcc69c10ab12bd782a0b53779dbd1cc0e2aa1Yorke Lee ((HostInterface) activity).setDragDropController(mListView.getDragDropController()); 2953cefcc69c10ab12bd782a0b53779dbd1cc0e2aa1Yorke Lee } catch (ClassCastException e) { 2963cefcc69c10ab12bd782a0b53779dbd1cc0e2aa1Yorke Lee throw new ClassCastException(activity.toString() 2973cefcc69c10ab12bd782a0b53779dbd1cc0e2aa1Yorke Lee + " must implement OnDragDropListener and HostInterface"); 2983cefcc69c10ab12bd782a0b53779dbd1cc0e2aa1Yorke Lee } 2993cefcc69c10ab12bd782a0b53779dbd1cc0e2aa1Yorke Lee 300e00c9fe163d19ee380b922e3fcbe736216d78cccYorke Lee try { 301e00c9fe163d19ee380b922e3fcbe736216d78cccYorke Lee mPhoneNumberPickerActionListener = (OnPhoneNumberPickerActionListener) activity; 302e00c9fe163d19ee380b922e3fcbe736216d78cccYorke Lee } catch (ClassCastException e) { 303e00c9fe163d19ee380b922e3fcbe736216d78cccYorke Lee throw new ClassCastException(activity.toString() 304e00c9fe163d19ee380b922e3fcbe736216d78cccYorke Lee + " must implement PhoneFavoritesFragment.listener"); 305e00c9fe163d19ee380b922e3fcbe736216d78cccYorke Lee } 306e00c9fe163d19ee380b922e3fcbe736216d78cccYorke Lee 3076b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee // Use initLoader() instead of restartLoader() to refraining unnecessary reload. 3086b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee // This method call implicitly assures ContactTileLoaderListener's onLoadFinished() will 3096b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee // be called, on which we'll check if "all" contacts should be reloaded again or not. 310c16ea5ad67bf454158b364dec2f26c95a879c350Yorke Lee if (PermissionsUtil.hasContactsPermissions(activity)) { 311c16ea5ad67bf454158b364dec2f26c95a879c350Yorke Lee getLoaderManager().initLoader(LOADER_ID_CONTACT_TILE, null, mContactTileLoaderListener); 312c16ea5ad67bf454158b364dec2f26c95a879c350Yorke Lee } else { 313c16ea5ad67bf454158b364dec2f26c95a879c350Yorke Lee setEmptyViewVisibility(true); 314c16ea5ad67bf454158b364dec2f26c95a879c350Yorke Lee } 3156b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee } 3166b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee 3176b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee /** 3186b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee * {@inheritDoc} 3196b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee * 3206b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee * This is only effective for elements provided by {@link #mContactTileAdapter}. 3216b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee * {@link #mContactTileAdapter} has its own logic for click events. 3226b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee */ 3236b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee @Override 3246b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 3256b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee final int contactTileAdapterCount = mContactTileAdapter.getCount(); 3266b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee if (position <= contactTileAdapterCount) { 3276b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee Log.e(TAG, "onItemClick() event for unexpected position. " 3286b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee + "The position " + position + " is before \"all\" section. Ignored."); 3296b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee } 3306b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee } 3316b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee 332c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee /** 333765734c1d602c9a6d166d653b3684e6408b771c4Yorke Lee * Cache the current view offsets into memory. Once a relayout of views in the ListView 334765734c1d602c9a6d166d653b3684e6408b771c4Yorke Lee * has happened due to a dataset change, the cached offsets are used to create animations 335765734c1d602c9a6d166d653b3684e6408b771c4Yorke Lee * that slide views from their previous positions to their new ones, to give the appearance 336765734c1d602c9a6d166d653b3684e6408b771c4Yorke Lee * that the views are sliding into their new positions. 337c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee */ 3384ed7db87e6c0e71b2f656e77de938f3579bc36bfYorke Lee private void saveOffsets(int removedItemHeight) { 339c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee final int firstVisiblePosition = mListView.getFirstVisiblePosition(); 340c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee if (DEBUG) { 341c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee Log.d(TAG, "Child count : " + mListView.getChildCount()); 342c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee } 343c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee for (int i = 0; i < mListView.getChildCount(); i++) { 344c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee final View child = mListView.getChildAt(i); 345c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee final int position = firstVisiblePosition + i; 346e48124fa2d295c68cdb95f962ef8bd6d35a7c145Anthony Lee // Since we are getting the position from mListView and then querying 347e48124fa2d295c68cdb95f962ef8bd6d35a7c145Anthony Lee // mContactTileAdapter, its very possible that things are out of sync 348e48124fa2d295c68cdb95f962ef8bd6d35a7c145Anthony Lee // and we might index out of bounds. Let's make sure that this doesn't happen. 349e48124fa2d295c68cdb95f962ef8bd6d35a7c145Anthony Lee if (!mContactTileAdapter.isIndexInBound(position)) { 350e48124fa2d295c68cdb95f962ef8bd6d35a7c145Anthony Lee continue; 351e48124fa2d295c68cdb95f962ef8bd6d35a7c145Anthony Lee } 352efb2d9c2e32ca4ed434ff785c4b3d18c9e08db6dYorke Lee final long itemId = mContactTileAdapter.getItemId(position); 353c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee if (DEBUG) { 354c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee Log.d(TAG, "Saving itemId: " + itemId + " for listview child " + i + " Top: " 355c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee + child.getTop()); 356c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee } 357c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee mItemIdTopMap.put(itemId, child.getTop()); 358c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee mItemIdLeftMap.put(itemId, child.getLeft()); 359c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee } 360efb2d9c2e32ca4ed434ff785c4b3d18c9e08db6dYorke Lee mItemIdTopMap.put(KEY_REMOVED_ITEM_HEIGHT, removedItemHeight); 361c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee } 362c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee 363c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee /* 364efb2d9c2e32ca4ed434ff785c4b3d18c9e08db6dYorke Lee * Performs animations for the gridView 365c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee */ 366efb2d9c2e32ca4ed434ff785c4b3d18c9e08db6dYorke Lee private void animateGridView(final long... idsInPlace) { 36720d682f9a586da495f180bfb6a445520d027c74dHongwei Wang if (mItemIdTopMap.isEmpty()) { 368c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee // Don't do animations if the database is being queried for the first time and 369c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee // the previous item offsets have not been cached, or the user hasn't done anything 370c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee // (dragging, swiping etc) that requires an animation. 371c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee return; 372c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee } 3734ed7db87e6c0e71b2f656e77de938f3579bc36bfYorke Lee 374c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee final ViewTreeObserver observer = mListView.getViewTreeObserver(); 375c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { 376c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee @SuppressWarnings("unchecked") 377c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee @Override 378c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee public boolean onPreDraw() { 379c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee observer.removeOnPreDrawListener(this); 380c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee final int firstVisiblePosition = mListView.getFirstVisiblePosition(); 3815b2e21098d84e94fd629e5e07c3bbb66bf9b5d95Hongwei Wang final AnimatorSet animSet = new AnimatorSet(); 3825b2e21098d84e94fd629e5e07c3bbb66bf9b5d95Hongwei Wang final ArrayList<Animator> animators = new ArrayList<Animator>(); 383c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee for (int i = 0; i < mListView.getChildCount(); i++) { 384c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee final View child = mListView.getChildAt(i); 385c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee int position = firstVisiblePosition + i; 386c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee 387e48124fa2d295c68cdb95f962ef8bd6d35a7c145Anthony Lee // Since we are getting the position from mListView and then querying 388e48124fa2d295c68cdb95f962ef8bd6d35a7c145Anthony Lee // mContactTileAdapter, its very possible that things are out of sync 389e48124fa2d295c68cdb95f962ef8bd6d35a7c145Anthony Lee // and we might index out of bounds. Let's make sure that this doesn't happen. 390e48124fa2d295c68cdb95f962ef8bd6d35a7c145Anthony Lee if (!mContactTileAdapter.isIndexInBound(position)) { 391e48124fa2d295c68cdb95f962ef8bd6d35a7c145Anthony Lee continue; 392e48124fa2d295c68cdb95f962ef8bd6d35a7c145Anthony Lee } 393e48124fa2d295c68cdb95f962ef8bd6d35a7c145Anthony Lee 394efb2d9c2e32ca4ed434ff785c4b3d18c9e08db6dYorke Lee final long itemId = mContactTileAdapter.getItemId(position); 395c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee 3964911300ae3fa7ab186ee271f8bc431b65a819a3cHongwei Wang if (containsId(idsInPlace, itemId)) { 3975b2e21098d84e94fd629e5e07c3bbb66bf9b5d95Hongwei Wang animators.add(ObjectAnimator.ofFloat( 3985b2e21098d84e94fd629e5e07c3bbb66bf9b5d95Hongwei Wang child, "alpha", 0.0f, 1.0f)); 3995b2e21098d84e94fd629e5e07c3bbb66bf9b5d95Hongwei Wang break; 400f59250951cf47d81fda125e9bab324d66ed75214Mindy Pereira } else { 401f59250951cf47d81fda125e9bab324d66ed75214Mindy Pereira Integer startTop = mItemIdTopMap.get(itemId); 402efb2d9c2e32ca4ed434ff785c4b3d18c9e08db6dYorke Lee Integer startLeft = mItemIdLeftMap.get(itemId); 403f59250951cf47d81fda125e9bab324d66ed75214Mindy Pereira final int top = child.getTop(); 404efb2d9c2e32ca4ed434ff785c4b3d18c9e08db6dYorke Lee final int left = child.getLeft(); 405efb2d9c2e32ca4ed434ff785c4b3d18c9e08db6dYorke Lee int deltaX = 0; 406efb2d9c2e32ca4ed434ff785c4b3d18c9e08db6dYorke Lee int deltaY = 0; 407efb2d9c2e32ca4ed434ff785c4b3d18c9e08db6dYorke Lee 408efb2d9c2e32ca4ed434ff785c4b3d18c9e08db6dYorke Lee if (startLeft != null) { 409efb2d9c2e32ca4ed434ff785c4b3d18c9e08db6dYorke Lee if (startLeft != left) { 410efb2d9c2e32ca4ed434ff785c4b3d18c9e08db6dYorke Lee deltaX = startLeft - left; 411efb2d9c2e32ca4ed434ff785c4b3d18c9e08db6dYorke Lee animators.add(ObjectAnimator.ofFloat( 412efb2d9c2e32ca4ed434ff785c4b3d18c9e08db6dYorke Lee child, "translationX", deltaX, 0.0f)); 413efb2d9c2e32ca4ed434ff785c4b3d18c9e08db6dYorke Lee } 414efb2d9c2e32ca4ed434ff785c4b3d18c9e08db6dYorke Lee } 415efb2d9c2e32ca4ed434ff785c4b3d18c9e08db6dYorke Lee 416f59250951cf47d81fda125e9bab324d66ed75214Mindy Pereira if (startTop != null) { 417f59250951cf47d81fda125e9bab324d66ed75214Mindy Pereira if (startTop != top) { 418efb2d9c2e32ca4ed434ff785c4b3d18c9e08db6dYorke Lee deltaY = startTop - top; 419efb2d9c2e32ca4ed434ff785c4b3d18c9e08db6dYorke Lee animators.add(ObjectAnimator.ofFloat( 420efb2d9c2e32ca4ed434ff785c4b3d18c9e08db6dYorke Lee child, "translationY", deltaY, 0.0f)); 4214ed7db87e6c0e71b2f656e77de938f3579bc36bfYorke Lee } 4225b2e21098d84e94fd629e5e07c3bbb66bf9b5d95Hongwei Wang } 423efb2d9c2e32ca4ed434ff785c4b3d18c9e08db6dYorke Lee 4245b2e21098d84e94fd629e5e07c3bbb66bf9b5d95Hongwei Wang if (DEBUG) { 4255b2e21098d84e94fd629e5e07c3bbb66bf9b5d95Hongwei Wang Log.d(TAG, "Found itemId: " + itemId + " for listview child " + i + 4265b2e21098d84e94fd629e5e07c3bbb66bf9b5d95Hongwei Wang " Top: " + top + 427efb2d9c2e32ca4ed434ff785c4b3d18c9e08db6dYorke Lee " Delta: " + deltaY); 428f59250951cf47d81fda125e9bab324d66ed75214Mindy Pereira } 429c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee } 430c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee } 4315b2e21098d84e94fd629e5e07c3bbb66bf9b5d95Hongwei Wang 4325b2e21098d84e94fd629e5e07c3bbb66bf9b5d95Hongwei Wang if (animators.size() > 0) { 4335b2e21098d84e94fd629e5e07c3bbb66bf9b5d95Hongwei Wang animSet.setDuration(mAnimationDuration).playTogether(animators); 4345b2e21098d84e94fd629e5e07c3bbb66bf9b5d95Hongwei Wang animSet.start(); 4355b2e21098d84e94fd629e5e07c3bbb66bf9b5d95Hongwei Wang } 4365b2e21098d84e94fd629e5e07c3bbb66bf9b5d95Hongwei Wang 437c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee mItemIdTopMap.clear(); 438c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee mItemIdLeftMap.clear(); 439c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee return true; 440c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee } 441c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee }); 442c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee } 443c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee 444c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee private boolean containsId(long[] ids, long target) { 445c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee // Linear search on array is fine because this is typically only 0-1 elements long 446c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee for (int i = 0; i < ids.length; i++) { 447c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee if (ids[i] == target) { 448c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee return true; 449c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee } 450c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee } 451c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee return false; 452c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee } 453c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee 454c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee @Override 455c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee public void onDataSetChangedForAnimation(long... idsInPlace) { 456efb2d9c2e32ca4ed434ff785c4b3d18c9e08db6dYorke Lee animateGridView(idsInPlace); 457c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee } 458c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee 459c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee @Override 460c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee public void cacheOffsetsForDatasetChange() { 4614ed7db87e6c0e71b2f656e77de938f3579bc36bfYorke Lee saveOffsets(0); 462c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee } 463764f652b451d27282cfaf73407d31c9522e6cb0eBrian Attwell 464764f652b451d27282cfaf73407d31c9522e6cb0eBrian Attwell public AbsListView getListView() { 465764f652b451d27282cfaf73407d31c9522e6cb0eBrian Attwell return mListView; 466764f652b451d27282cfaf73407d31c9522e6cb0eBrian Attwell } 46738019af70eb1ca084d36291390bbc54dc81027deYorke Lee 46838019af70eb1ca084d36291390bbc54dc81027deYorke Lee @Override 469575ae388961252a771488c357e425fca191594b2Yorke Lee public void onEmptyViewActionButtonClicked() { 47038019af70eb1ca084d36291390bbc54dc81027deYorke Lee final Activity activity = getActivity(); 47138019af70eb1ca084d36291390bbc54dc81027deYorke Lee if (activity == null) { 47238019af70eb1ca084d36291390bbc54dc81027deYorke Lee return; 47338019af70eb1ca084d36291390bbc54dc81027deYorke Lee } 47438019af70eb1ca084d36291390bbc54dc81027deYorke Lee 47538019af70eb1ca084d36291390bbc54dc81027deYorke Lee if (!PermissionsUtil.hasPermission(activity, READ_CONTACTS)) { 4767e1a68556c419c4b9b1eda9247e80262615fa809Yorke Lee requestPermissions(new String[] {READ_CONTACTS}, READ_CONTACTS_PERMISSION_REQUEST_CODE); 47738019af70eb1ca084d36291390bbc54dc81027deYorke Lee } else { 47838019af70eb1ca084d36291390bbc54dc81027deYorke Lee // Switch tabs 47938019af70eb1ca084d36291390bbc54dc81027deYorke Lee ((HostInterface) activity).showAllContactsTab(); 48038019af70eb1ca084d36291390bbc54dc81027deYorke Lee } 48138019af70eb1ca084d36291390bbc54dc81027deYorke Lee } 4827e1a68556c419c4b9b1eda9247e80262615fa809Yorke Lee 4837e1a68556c419c4b9b1eda9247e80262615fa809Yorke Lee @Override 4847e1a68556c419c4b9b1eda9247e80262615fa809Yorke Lee public void onRequestPermissionsResult(int requestCode, String[] permissions, 4857e1a68556c419c4b9b1eda9247e80262615fa809Yorke Lee int[] grantResults) { 4867e1a68556c419c4b9b1eda9247e80262615fa809Yorke Lee if (requestCode == READ_CONTACTS_PERMISSION_REQUEST_CODE) { 4877e1a68556c419c4b9b1eda9247e80262615fa809Yorke Lee if (grantResults.length == 1 && PackageManager.PERMISSION_GRANTED == grantResults[0]) { 4887e1a68556c419c4b9b1eda9247e80262615fa809Yorke Lee PermissionsUtil.notifyPermissionGranted(getActivity(), READ_CONTACTS); 4897e1a68556c419c4b9b1eda9247e80262615fa809Yorke Lee } 4907e1a68556c419c4b9b1eda9247e80262615fa809Yorke Lee } 4917e1a68556c419c4b9b1eda9247e80262615fa809Yorke Lee } 4926b049128c51b90e17ae14856d98130a22d3a5433Yorke Lee} 493