From d999b71452baebec789f6f58f1955d30e834826d Mon Sep 17 00:00:00 2001 From: Yorke Lee Date: Wed, 23 Apr 2014 15:10:58 -0700 Subject: Rename classes Renamed PhoneFavoriteFragment to SpeedDialFragment Renamed PhoneFavoriteMergedAdapter to ShortcutCardsAdapter Change-Id: I5b16ff576332b44c10e1abb44689147cd41c26b5 --- src/com/android/dialer/DialtactsActivity.java | 10 +- src/com/android/dialer/list/ListsFragment.java | 8 +- .../android/dialer/list/PhoneFavoriteFragment.java | 420 --------------------- .../dialer/list/PhoneFavoriteMergedAdapter.java | 272 ------------- .../android/dialer/list/ShortcutCardsAdapter.java | 272 +++++++++++++ src/com/android/dialer/list/SpeedDialFragment.java | 415 ++++++++++++++++++++ .../dialer/list/TileInteractionTeaserView.java | 4 +- 7 files changed, 698 insertions(+), 703 deletions(-) delete mode 100644 src/com/android/dialer/list/PhoneFavoriteFragment.java delete mode 100644 src/com/android/dialer/list/PhoneFavoriteMergedAdapter.java create mode 100644 src/com/android/dialer/list/ShortcutCardsAdapter.java create mode 100644 src/com/android/dialer/list/SpeedDialFragment.java diff --git a/src/com/android/dialer/DialtactsActivity.java b/src/com/android/dialer/DialtactsActivity.java index c449e09bf..3f490069c 100644 --- a/src/com/android/dialer/DialtactsActivity.java +++ b/src/com/android/dialer/DialtactsActivity.java @@ -74,7 +74,7 @@ import com.android.dialer.list.DragDropController; import com.android.dialer.list.ListsFragment; import com.android.dialer.list.OnDragDropListener; import com.android.dialer.list.OnListFragmentScrolledListener; -import com.android.dialer.list.PhoneFavoriteFragment; +import com.android.dialer.list.SpeedDialFragment; import com.android.dialer.list.PhoneFavoriteTileView; import com.android.dialer.list.PhoneFavoriteSquareTileView; import com.android.dialer.list.RegularSearchFragment; @@ -95,7 +95,7 @@ public class DialtactsActivity extends TransactionSafeActivity implements View.O OnListFragmentScrolledListener, DialpadFragment.HostInterface, ListsFragment.HostInterface, - PhoneFavoriteFragment.HostInterface, + SpeedDialFragment.HostInterface, OnDragDropListener, View.OnLongClickListener, OnPhoneNumberPickerActionListener { private static final String TAG = "DialtactsActivity"; @@ -207,7 +207,7 @@ public class DialtactsActivity extends TransactionSafeActivity implements View.O public void show() { final Menu menu = getMenu(); final MenuItem clearFrequents = menu.findItem(R.id.menu_clear_frequents); - // TODO: Check mPhoneFavoriteFragment.hasFrequents() + // TODO: Check mSpeedDialFragment.hasFrequents() clearFrequents.setVisible(true); super.show(); } @@ -483,7 +483,7 @@ public class DialtactsActivity extends TransactionSafeActivity implements View.O return true; case R.id.menu_clear_frequents: // TODO: This should be enabled/disabled based on - // PhoneFavoritesFragments.hasFrequents + // SpeedDialFragment.hasFrequents ClearFrequentsDialog.show(getFragmentManager()); return true; case R.id.menu_call_settings: @@ -940,7 +940,7 @@ public class DialtactsActivity extends TransactionSafeActivity implements View.O public void onDroppedOnRemove() {} /** - * Allows the PhoneFavoriteFragment to attach the drag controller to mRemoveViewContainer + * Allows the SpeedDialFragment to attach the drag controller to mRemoveViewContainer * once it has been attached to the activity. */ @Override diff --git a/src/com/android/dialer/list/ListsFragment.java b/src/com/android/dialer/list/ListsFragment.java index d6ea2ad43..676b3b075 100644 --- a/src/com/android/dialer/list/ListsFragment.java +++ b/src/com/android/dialer/list/ListsFragment.java @@ -65,13 +65,13 @@ public class ListsFragment extends Fragment implements CallLogQueryHandler.Liste private ViewPager mViewPager; private ViewPagerAdapter mViewPagerAdapter; - private PhoneFavoriteFragment mSpeedDialFragment; + private SpeedDialFragment mSpeedDialFragment; private CallLogFragment mRecentsFragment; private AllContactsFragment mAllContactsFragment; private String[] mTabTitles; - private PhoneFavoriteMergedAdapter mMergedAdapter; + private ShortcutCardsAdapter mMergedAdapter; private CallLogAdapter mCallLogAdapter; private CallLogQueryHandler mCallLogQueryHandler; @@ -116,7 +116,7 @@ public class ListsFragment extends Fragment implements CallLogQueryHandler.Liste public Fragment getItem(int position) { switch (position) { case TAB_INDEX_SPEED_DIAL: - mSpeedDialFragment = new PhoneFavoriteFragment(); + mSpeedDialFragment = new SpeedDialFragment(); return mSpeedDialFragment; case TAB_INDEX_RECENTS: mRecentsFragment = new CallLogFragment(CallLogQueryHandler.CALL_TYPE_ALL, @@ -168,7 +168,7 @@ public class ListsFragment extends Fragment implements CallLogQueryHandler.Liste mCallLogAdapter = ObjectFactory.newCallLogAdapter(getActivity(), this, new ContactInfoHelper(getActivity(), currentCountryIso), false, false); - mMergedAdapter = new PhoneFavoriteMergedAdapter(getActivity(), this, mCallLogAdapter); + mMergedAdapter = new ShortcutCardsAdapter(getActivity(), this, mCallLogAdapter); } @Override diff --git a/src/com/android/dialer/list/PhoneFavoriteFragment.java b/src/com/android/dialer/list/PhoneFavoriteFragment.java deleted file mode 100644 index 05e2d44d4..000000000 --- a/src/com/android/dialer/list/PhoneFavoriteFragment.java +++ /dev/null @@ -1,420 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.dialer.list; - -import android.animation.Animator; -import android.animation.AnimatorSet; -import android.animation.ObjectAnimator; -import android.app.Activity; -import android.app.Fragment; -import android.app.LoaderManager; -import android.content.CursorLoader; -import android.content.Loader; -import android.database.Cursor; -import android.graphics.Rect; -import android.net.Uri; -import android.os.Bundle; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.view.ViewTreeObserver; -import android.widget.AbsListView; -import android.widget.AdapterView; -import android.widget.AdapterView.OnItemClickListener; -import android.widget.ImageView; -import android.widget.ListView; -import android.widget.RelativeLayout; -import android.widget.RelativeLayout.LayoutParams; - -import com.android.contacts.common.ContactPhotoManager; -import com.android.contacts.common.ContactTileLoaderFactory; -import com.android.contacts.common.list.ContactTileView; -import com.android.contacts.common.list.OnPhoneNumberPickerActionListener; -import com.android.dialer.R; - -import java.util.ArrayList; -import java.util.HashMap; - -/** - * Fragment for Phone UI's favorite screen. - * - * This fragment contains three kinds of contacts in one screen: "starred", "frequent", and "all" - * contacts. To show them at once, this merges results from {@link com.android.contacts.common.list.ContactTileAdapter} and - * {@link com.android.contacts.common.list.PhoneNumberListAdapter} into one unified list using {@link PhoneFavoriteMergedAdapter}. - * A contact filter header is also inserted between those adapters' results. - */ -public class PhoneFavoriteFragment extends Fragment implements OnItemClickListener, - PhoneFavoritesTileAdapter.OnDataSetChangedForAnimationListener { - - /** - * By default, the animation code assumes that all items in a list view are of the same height - * when animating new list items into view (e.g. from the bottom of the screen into view). - * This can cause incorrect translation offsets when a item that is larger or smaller than - * other list item is removed from the list. This key is used to provide the actual height - * of the removed object so that the actual translation appears correct to the user. - */ - private static final long KEY_REMOVED_ITEM_HEIGHT = Long.MAX_VALUE; - - private static final String TAG = PhoneFavoriteFragment.class.getSimpleName(); - private static final boolean DEBUG = false; - - private int mAnimationDuration; - - /** - * Used with LoaderManager. - */ - private static int LOADER_ID_CONTACT_TILE = 1; - - public interface HostInterface { - public void setDragDropController(DragDropController controller); - } - - private class ContactTileLoaderListener implements LoaderManager.LoaderCallbacks { - @Override - public CursorLoader onCreateLoader(int id, Bundle args) { - if (DEBUG) Log.d(TAG, "ContactTileLoaderListener#onCreateLoader."); - return ContactTileLoaderFactory.createStrequentPhoneOnlyLoader(getActivity()); - } - - @Override - public void onLoadFinished(Loader loader, Cursor data) { - if (DEBUG) Log.d(TAG, "ContactTileLoaderListener#onLoadFinished"); - mContactTileAdapter.setContactCursor(data); - setEmptyViewVisibility(mContactTileAdapter.getCount() == 0); - } - - @Override - public void onLoaderReset(Loader loader) { - if (DEBUG) Log.d(TAG, "ContactTileLoaderListener#onLoaderReset. "); - } - } - - private class ContactTileAdapterListener implements ContactTileView.Listener { - @Override - public void onContactSelected(Uri contactUri, Rect targetRect) { - if (mPhoneNumberPickerActionListener != null) { - mPhoneNumberPickerActionListener.onPickPhoneNumberAction(contactUri); - } - } - - @Override - public void onCallNumberDirectly(String phoneNumber) { - if (mPhoneNumberPickerActionListener != null) { - mPhoneNumberPickerActionListener.onCallNumberDirectly(phoneNumber); - } - } - - @Override - public int getApproximateTileWidth() { - return getView().getWidth(); - } - } - - private class ScrollListener implements ListView.OnScrollListener { - @Override - public void onScroll(AbsListView view, - int firstVisibleItem, int visibleItemCount, int totalItemCount) { - if (mActivityScrollListener != null) { - mActivityScrollListener.onListFragmentScroll(firstVisibleItem, visibleItemCount, - totalItemCount); - } - } - - @Override - public void onScrollStateChanged(AbsListView view, int scrollState) { - mActivityScrollListener.onListFragmentScrollStateChange(scrollState); - } - } - - private OnPhoneNumberPickerActionListener mPhoneNumberPickerActionListener; - - private OnListFragmentScrolledListener mActivityScrollListener; - private PhoneFavoritesTileAdapter mContactTileAdapter; - - private View mParentView; - - private PhoneFavoriteListView mListView; - - private View mPhoneFavoritesMenu; - private View mContactTileFrame; - - private TileInteractionTeaserView mTileInteractionTeaserView; - - private final HashMap mItemIdTopMap = new HashMap(); - private final HashMap mItemIdLeftMap = new HashMap(); - - /** - * Layout used when there are no favorites. - */ - private View mEmptyView; - - private final ContactTileView.Listener mContactTileAdapterListener = - new ContactTileAdapterListener(); - private final LoaderManager.LoaderCallbacks mContactTileLoaderListener = - new ContactTileLoaderListener(); - private final ScrollListener mScrollListener = new ScrollListener(); - - @Override - public void onAttach(Activity activity) { - if (DEBUG) Log.d(TAG, "onAttach()"); - super.onAttach(activity); - - // Construct two base adapters which will become part of PhoneFavoriteMergedAdapter. - // We don't construct the resultant adapter at this moment since it requires LayoutInflater - // that will be available on onCreateView(). - mContactTileAdapter = new PhoneFavoritesTileAdapter(activity, mContactTileAdapterListener, - this); - mContactTileAdapter.setPhotoLoader(ContactPhotoManager.getInstance(activity)); - } - - @Override - public void onCreate(Bundle savedState) { - if (DEBUG) Log.d(TAG, "onCreate()"); - super.onCreate(savedState); - - mAnimationDuration = getResources().getInteger(R.integer.fade_duration); - } - - @Override - public void onResume() { - super.onResume(); - - getLoaderManager().getLoader(LOADER_ID_CONTACT_TILE).forceLoad(); - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - mParentView = inflater.inflate(R.layout.phone_favorites_fragment, container, false); - - mListView = (PhoneFavoriteListView) mParentView.findViewById(R.id.contact_tile_list); - mListView.setOnItemClickListener(this); - mListView.setVerticalScrollBarEnabled(false); - mListView.setVerticalScrollbarPosition(View.SCROLLBAR_POSITION_RIGHT); - mListView.setScrollBarStyle(ListView.SCROLLBARS_OUTSIDE_OVERLAY); - mListView.getDragDropController().addOnDragDropListener(mContactTileAdapter); - - final ImageView dragShadowOverlay = - (ImageView) mParentView.findViewById(R.id.contact_tile_drag_shadow_overlay); - mListView.setDragShadowOverlay(dragShadowOverlay); - - mEmptyView = mParentView.findViewById(R.id.phone_no_favorites_view); - - mPhoneFavoritesMenu = inflater.inflate(R.layout.phone_favorites_menu, mListView, false); - - mContactTileFrame = mParentView.findViewById(R.id.contact_tile_frame); - - mTileInteractionTeaserView = (TileInteractionTeaserView) inflater.inflate( - R.layout.tile_interactions_teaser_view, mListView, false); - - mListView.setAdapter(mContactTileAdapter); - - mListView.setOnScrollListener(mScrollListener); - mListView.setFastScrollEnabled(false); - mListView.setFastScrollAlwaysVisible(false); - - return mParentView; - } - - public boolean hasFrequents() { - if (mContactTileAdapter == null) return false; - return mContactTileAdapter.getNumFrequents() > 0; - } - - /* package */ void setEmptyViewVisibility(final boolean visible) { - final int previousVisibility = mEmptyView.getVisibility(); - final int newVisibility = visible ? View.VISIBLE : View.GONE; - - if (previousVisibility != newVisibility) { - final RelativeLayout.LayoutParams params = (LayoutParams) mContactTileFrame - .getLayoutParams(); - params.height = visible ? LayoutParams.WRAP_CONTENT : LayoutParams.MATCH_PARENT; - mContactTileFrame.setLayoutParams(params); - mEmptyView.setVisibility(newVisibility); - } - } - - @Override - public void onStart() { - super.onStart(); - - final Activity activity = getActivity(); - - try { - mActivityScrollListener = (OnListFragmentScrolledListener) activity; - } catch (ClassCastException e) { - throw new ClassCastException(activity.toString() - + " must implement OnListFragmentScrolledListener"); - } - - try { - OnDragDropListener listener = (OnDragDropListener) activity; - mListView.getDragDropController().addOnDragDropListener(listener); - ((HostInterface) activity).setDragDropController(mListView.getDragDropController()); - } catch (ClassCastException e) { - throw new ClassCastException(activity.toString() - + " must implement OnDragDropListener and HostInterface"); - } - - try { - mPhoneNumberPickerActionListener = (OnPhoneNumberPickerActionListener) activity; - } catch (ClassCastException e) { - throw new ClassCastException(activity.toString() - + " must implement PhoneFavoritesFragment.listener"); - } - - // Use initLoader() instead of restartLoader() to refraining unnecessary reload. - // This method call implicitly assures ContactTileLoaderListener's onLoadFinished() will - // be called, on which we'll check if "all" contacts should be reloaded again or not. - getLoaderManager().initLoader(LOADER_ID_CONTACT_TILE, null, mContactTileLoaderListener); - } - - /** - * {@inheritDoc} - * - * This is only effective for elements provided by {@link #mContactTileAdapter}. - * {@link #mContactTileAdapter} has its own logic for click events. - */ - @Override - public void onItemClick(AdapterView parent, View view, int position, long id) { - final int contactTileAdapterCount = mContactTileAdapter.getCount(); - if (position <= contactTileAdapterCount) { - Log.e(TAG, "onItemClick() event for unexpected position. " - + "The position " + position + " is before \"all\" section. Ignored."); - } - } - - /** - * Cache the current view offsets into memory. Once a relayout of views in the ListView - * has happened due to a dataset change, the cached offsets are used to create animations - * that slide views from their previous positions to their new ones, to give the appearance - * that the views are sliding into their new positions. - */ - private void saveOffsets(int removedItemHeight) { - final int firstVisiblePosition = mListView.getFirstVisiblePosition(); - if (DEBUG) { - Log.d(TAG, "Child count : " + mListView.getChildCount()); - } - for (int i = 0; i < mListView.getChildCount(); i++) { - final View child = mListView.getChildAt(i); - final int position = firstVisiblePosition + i; - final long itemId = mContactTileAdapter.getItemId(position); - if (DEBUG) { - Log.d(TAG, "Saving itemId: " + itemId + " for listview child " + i + " Top: " - + child.getTop()); - } - mItemIdTopMap.put(itemId, child.getTop()); - mItemIdLeftMap.put(itemId, child.getLeft()); - } - - mItemIdTopMap.put(KEY_REMOVED_ITEM_HEIGHT, removedItemHeight); - } - - /* - * Performs animations for the gridView - */ - private void animateGridView(final long... idsInPlace) { - if (mItemIdTopMap.isEmpty()) { - // Don't do animations if the database is being queried for the first time and - // the previous item offsets have not been cached, or the user hasn't done anything - // (dragging, swiping etc) that requires an animation. - return; - } - - final ViewTreeObserver observer = mListView.getViewTreeObserver(); - observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { - @SuppressWarnings("unchecked") - @Override - public boolean onPreDraw() { - observer.removeOnPreDrawListener(this); - final int firstVisiblePosition = mListView.getFirstVisiblePosition(); - final AnimatorSet animSet = new AnimatorSet(); - final ArrayList animators = new ArrayList(); - for (int i = 0; i < mListView.getChildCount(); i++) { - final View child = mListView.getChildAt(i); - int position = firstVisiblePosition + i; - - final long itemId = mContactTileAdapter.getItemId(position); - - if (containsId(idsInPlace, itemId)) { - animators.add(ObjectAnimator.ofFloat( - child, "alpha", 0.0f, 1.0f)); - break; - } else { - Integer startTop = mItemIdTopMap.get(itemId); - Integer startLeft = mItemIdLeftMap.get(itemId); - final int top = child.getTop(); - final int left = child.getLeft(); - int deltaX = 0; - int deltaY = 0; - - if (startLeft != null) { - if (startLeft != left) { - deltaX = startLeft - left; - animators.add(ObjectAnimator.ofFloat( - child, "translationX", deltaX, 0.0f)); - } - } - - if (startTop != null) { - if (startTop != top) { - deltaY = startTop - top; - animators.add(ObjectAnimator.ofFloat( - child, "translationY", deltaY, 0.0f)); - } - } - - if (DEBUG) { - Log.d(TAG, "Found itemId: " + itemId + " for listview child " + i + - " Top: " + top + - " Delta: " + deltaY); - } - } - } - - if (animators.size() > 0) { - animSet.setDuration(mAnimationDuration).playTogether(animators); - animSet.start(); - } - - mItemIdTopMap.clear(); - mItemIdLeftMap.clear(); - return true; - } - }); - } - - private boolean containsId(long[] ids, long target) { - // Linear search on array is fine because this is typically only 0-1 elements long - for (int i = 0; i < ids.length; i++) { - if (ids[i] == target) { - return true; - } - } - return false; - } - - @Override - public void onDataSetChangedForAnimation(long... idsInPlace) { - animateGridView(idsInPlace); - } - - @Override - public void cacheOffsetsForDatasetChange() { - saveOffsets(0); - } -} diff --git a/src/com/android/dialer/list/PhoneFavoriteMergedAdapter.java b/src/com/android/dialer/list/PhoneFavoriteMergedAdapter.java deleted file mode 100644 index 122e0629e..000000000 --- a/src/com/android/dialer/list/PhoneFavoriteMergedAdapter.java +++ /dev/null @@ -1,272 +0,0 @@ -/* - * Copyright (C) 2011 Google Inc. - * Licensed to The Android Open Source Project. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.dialer.list; - -import android.content.Context; -import android.content.res.Resources; -import android.database.Cursor; -import android.database.DataSetObserver; -import android.view.MotionEvent; -import android.view.View; -import android.view.ViewConfiguration; -import android.view.ViewGroup; -import android.widget.BaseAdapter; -import android.widget.FrameLayout; - -import com.android.dialer.R; -import com.android.dialer.calllog.CallLogAdapter; -import com.android.dialer.calllog.CallLogNotificationsHelper; -import com.android.dialer.calllog.CallLogQueryHandler; -import com.android.dialer.list.SwipeHelper.OnItemGestureListener; -import com.android.dialer.list.SwipeHelper.SwipeHelperCallback; - -/** - * An adapter that displays call shortcuts from {@link com.android.dialer.calllog.CallLogAdapter} - * in the form of cards. - */ -public class PhoneFavoriteMergedAdapter extends BaseAdapter { - - private class CustomDataSetObserver extends DataSetObserver { - @Override - public void onChanged() { - notifyDataSetChanged(); - } - } - - private static final String TAG = PhoneFavoriteMergedAdapter.class.getSimpleName(); - - private final CallLogAdapter mCallLogAdapter; - private final ListsFragment mFragment; - - private final int mCallLogPadding; - - private final Context mContext; - - private final DataSetObserver mObserver; - - private final CallLogQueryHandler mCallLogQueryHandler; - - private final OnItemGestureListener mCallLogOnItemSwipeListener = - new OnItemGestureListener() { - @Override - public void onSwipe(View view) { - mCallLogQueryHandler.markNewCallsAsOld(); - mCallLogQueryHandler.markNewVoicemailsAsOld(); - CallLogNotificationsHelper.removeMissedCallNotifications(); - CallLogNotificationsHelper.updateVoicemailNotifications(mContext); - mFragment.dismissShortcut(view); - } - - @Override - public void onTouch() {} - - @Override - public boolean isSwipeEnabled() { - return true; - } - }; - - private final CallLogQueryHandler.Listener mCallLogQueryHandlerListener = - new CallLogQueryHandler.Listener() { - @Override - public void onVoicemailStatusFetched(Cursor statusCursor) {} - - @Override - public void onCallsFetched(Cursor combinedCursor) { - mCallLogAdapter.invalidateCache(); - mCallLogAdapter.changeCursor(combinedCursor); - mCallLogAdapter.notifyDataSetChanged(); - } - }; - - public PhoneFavoriteMergedAdapter(Context context, - ListsFragment fragment, - CallLogAdapter callLogAdapter) { - final Resources resources = context.getResources(); - mContext = context; - mFragment = fragment; - mCallLogPadding = resources.getDimensionPixelSize(R.dimen.recent_call_log_item_padding); - mCallLogAdapter = callLogAdapter; - mObserver = new CustomDataSetObserver(); - mCallLogAdapter.registerDataSetObserver(mObserver); - mCallLogQueryHandler = new CallLogQueryHandler(mContext.getContentResolver(), - mCallLogQueryHandlerListener); - } - - /** - * Determines the number of items in the adapter. - * mCallLogAdapter contains the item for the most recent caller. - * mContactTileAdapter contains the starred contacts. - * The +1 is to account for the presence of the favorites menu. - * - * @return Number of items in the adapter. - */ - @Override - public int getCount() { - return mCallLogAdapter.getCount(); - } - - @Override - public Object getItem(int position) { - return mCallLogAdapter.getItem(position); - } - - @Override - public long getItemId(int position) { - return position; - } - - @Override - public boolean hasStableIds() { - return true; - } - - /** - * Determine the number of view types present. - */ - @Override - public int getViewTypeCount() { - return mCallLogAdapter.getViewTypeCount(); - } - - @Override - public int getItemViewType(int position) { - return mCallLogAdapter.getItemViewType(position); - } - - @Override - public View getView(int position, View convertView, ViewGroup parent) { - final SwipeableCallLogRow wrapper; - if (convertView == null) { - wrapper = new SwipeableCallLogRow(mContext); - wrapper.setOnItemSwipeListener(mCallLogOnItemSwipeListener); - } else { - wrapper = (SwipeableCallLogRow) convertView; - } - - // Special case wrapper view for the most recent call log item. This allows - // us to create a card-like effect for the more recent call log item in - // the PhoneFavoriteMergedAdapter, but keep the original look of the item in - // the CallLogAdapter. - final View view = mCallLogAdapter.getView(position, convertView == null ? - null : wrapper.getChildAt(0), parent); - wrapper.removeAllViews(); - final View callLogItem = view.findViewById(R.id.call_log_list_item); - // Reset the internal call log item view if it is being recycled - callLogItem.setTranslationX(0); - callLogItem.setAlpha(1); - wrapper.addView(view); - return wrapper; - } - - @Override - public boolean areAllItemsEnabled() { - return mCallLogAdapter.areAllItemsEnabled(); - } - - @Override - public boolean isEnabled(int position) { - return mCallLogAdapter.isEnabled(position); - } - - /** - * The swipeable call log row. - */ - private class SwipeableCallLogRow extends FrameLayout implements SwipeHelperCallback { - private SwipeHelper mSwipeHelper; - private OnItemGestureListener mOnItemSwipeListener; - - public SwipeableCallLogRow(Context context) { - super(context); - final float densityScale = getResources().getDisplayMetrics().density; - final float pagingTouchSlop = ViewConfiguration.get(context) - .getScaledPagingTouchSlop(); - mSwipeHelper = new SwipeHelper(context, SwipeHelper.X, this, - densityScale, pagingTouchSlop); - } - - @Override - public void addView(View view) { - view.setBackgroundResource(R.drawable.ic_tile_for_recents_and_contact_tile); - - final FrameLayout.LayoutParams params = new FrameLayout.LayoutParams( - FrameLayout.LayoutParams.MATCH_PARENT, - FrameLayout.LayoutParams.WRAP_CONTENT); - params.setMargins(mCallLogPadding, mCallLogPadding, mCallLogPadding, mCallLogPadding); - view.setLayoutParams(params); - - super.addView(view); - } - - @Override - public View getChildAtPosition(MotionEvent ev) { - return getChildCount() > 0 ? getChildAt(0) : null; - } - - @Override - public View getChildContentView(View v) { - return v.findViewById(R.id.call_log_list_item); - } - - @Override - public void onScroll() {} - - @Override - public boolean canChildBeDismissed(View v) { - return true; - } - - @Override - public void onBeginDrag(View v) { - // We do this so the underlying ScrollView knows that it won't get - // the chance to intercept events anymore - requestDisallowInterceptTouchEvent(true); - } - - @Override - public void onChildDismissed(View v) { - if (v != null && mOnItemSwipeListener != null) { - mOnItemSwipeListener.onSwipe(v); - } - } - - @Override - public void onDragCancelled(View v) {} - - @Override - public boolean onInterceptTouchEvent(MotionEvent ev) { - if (mSwipeHelper != null) { - return mSwipeHelper.onInterceptTouchEvent(ev) || super.onInterceptTouchEvent(ev); - } else { - return super.onInterceptTouchEvent(ev); - } - } - - @Override - public boolean onTouchEvent(MotionEvent ev) { - if (mSwipeHelper != null) { - return mSwipeHelper.onTouchEvent(ev) || super.onTouchEvent(ev); - } else { - return super.onTouchEvent(ev); - } - } - - public void setOnItemSwipeListener(OnItemGestureListener listener) { - mOnItemSwipeListener = listener; - } - } -} diff --git a/src/com/android/dialer/list/ShortcutCardsAdapter.java b/src/com/android/dialer/list/ShortcutCardsAdapter.java new file mode 100644 index 000000000..4cca20b3d --- /dev/null +++ b/src/com/android/dialer/list/ShortcutCardsAdapter.java @@ -0,0 +1,272 @@ +/* + * Copyright (C) 2011 Google Inc. + * Licensed to The Android Open Source Project. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.dialer.list; + +import android.content.Context; +import android.content.res.Resources; +import android.database.Cursor; +import android.database.DataSetObserver; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewConfiguration; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.FrameLayout; + +import com.android.dialer.R; +import com.android.dialer.calllog.CallLogAdapter; +import com.android.dialer.calllog.CallLogNotificationsHelper; +import com.android.dialer.calllog.CallLogQueryHandler; +import com.android.dialer.list.SwipeHelper.OnItemGestureListener; +import com.android.dialer.list.SwipeHelper.SwipeHelperCallback; + +/** + * An adapter that displays call shortcuts from {@link com.android.dialer.calllog.CallLogAdapter} + * in the form of cards. + */ +public class ShortcutCardsAdapter extends BaseAdapter { + + private class CustomDataSetObserver extends DataSetObserver { + @Override + public void onChanged() { + notifyDataSetChanged(); + } + } + + private static final String TAG = ShortcutCardsAdapter.class.getSimpleName(); + + private final CallLogAdapter mCallLogAdapter; + private final ListsFragment mFragment; + + private final int mCallLogPadding; + + private final Context mContext; + + private final DataSetObserver mObserver; + + private final CallLogQueryHandler mCallLogQueryHandler; + + private final OnItemGestureListener mCallLogOnItemSwipeListener = + new OnItemGestureListener() { + @Override + public void onSwipe(View view) { + mCallLogQueryHandler.markNewCallsAsOld(); + mCallLogQueryHandler.markNewVoicemailsAsOld(); + CallLogNotificationsHelper.removeMissedCallNotifications(); + CallLogNotificationsHelper.updateVoicemailNotifications(mContext); + mFragment.dismissShortcut(view); + } + + @Override + public void onTouch() {} + + @Override + public boolean isSwipeEnabled() { + return true; + } + }; + + private final CallLogQueryHandler.Listener mCallLogQueryHandlerListener = + new CallLogQueryHandler.Listener() { + @Override + public void onVoicemailStatusFetched(Cursor statusCursor) {} + + @Override + public void onCallsFetched(Cursor combinedCursor) { + mCallLogAdapter.invalidateCache(); + mCallLogAdapter.changeCursor(combinedCursor); + mCallLogAdapter.notifyDataSetChanged(); + } + }; + + public ShortcutCardsAdapter(Context context, + ListsFragment fragment, + CallLogAdapter callLogAdapter) { + final Resources resources = context.getResources(); + mContext = context; + mFragment = fragment; + mCallLogPadding = resources.getDimensionPixelSize(R.dimen.recent_call_log_item_padding); + mCallLogAdapter = callLogAdapter; + mObserver = new CustomDataSetObserver(); + mCallLogAdapter.registerDataSetObserver(mObserver); + mCallLogQueryHandler = new CallLogQueryHandler(mContext.getContentResolver(), + mCallLogQueryHandlerListener); + } + + /** + * Determines the number of items in the adapter. + * mCallLogAdapter contains the item for the most recent caller. + * mContactTileAdapter contains the starred contacts. + * The +1 is to account for the presence of the favorites menu. + * + * @return Number of items in the adapter. + */ + @Override + public int getCount() { + return mCallLogAdapter.getCount(); + } + + @Override + public Object getItem(int position) { + return mCallLogAdapter.getItem(position); + } + + @Override + public long getItemId(int position) { + return position; + } + + @Override + public boolean hasStableIds() { + return true; + } + + /** + * Determine the number of view types present. + */ + @Override + public int getViewTypeCount() { + return mCallLogAdapter.getViewTypeCount(); + } + + @Override + public int getItemViewType(int position) { + return mCallLogAdapter.getItemViewType(position); + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + final SwipeableCallLogRow wrapper; + if (convertView == null) { + wrapper = new SwipeableCallLogRow(mContext); + wrapper.setOnItemSwipeListener(mCallLogOnItemSwipeListener); + } else { + wrapper = (SwipeableCallLogRow) convertView; + } + + // Special case wrapper view for the most recent call log item. This allows + // us to create a card-like effect for the more recent call log item in + // the PhoneFavoriteMergedAdapter, but keep the original look of the item in + // the CallLogAdapter. + final View view = mCallLogAdapter.getView(position, convertView == null ? + null : wrapper.getChildAt(0), parent); + wrapper.removeAllViews(); + final View callLogItem = view.findViewById(R.id.call_log_list_item); + // Reset the internal call log item view if it is being recycled + callLogItem.setTranslationX(0); + callLogItem.setAlpha(1); + wrapper.addView(view); + return wrapper; + } + + @Override + public boolean areAllItemsEnabled() { + return mCallLogAdapter.areAllItemsEnabled(); + } + + @Override + public boolean isEnabled(int position) { + return mCallLogAdapter.isEnabled(position); + } + + /** + * The swipeable call log row. + */ + private class SwipeableCallLogRow extends FrameLayout implements SwipeHelperCallback { + private SwipeHelper mSwipeHelper; + private OnItemGestureListener mOnItemSwipeListener; + + public SwipeableCallLogRow(Context context) { + super(context); + final float densityScale = getResources().getDisplayMetrics().density; + final float pagingTouchSlop = ViewConfiguration.get(context) + .getScaledPagingTouchSlop(); + mSwipeHelper = new SwipeHelper(context, SwipeHelper.X, this, + densityScale, pagingTouchSlop); + } + + @Override + public void addView(View view) { + view.setBackgroundResource(R.drawable.ic_tile_for_recents_and_contact_tile); + + final FrameLayout.LayoutParams params = new FrameLayout.LayoutParams( + FrameLayout.LayoutParams.MATCH_PARENT, + FrameLayout.LayoutParams.WRAP_CONTENT); + params.setMargins(mCallLogPadding, mCallLogPadding, mCallLogPadding, mCallLogPadding); + view.setLayoutParams(params); + + super.addView(view); + } + + @Override + public View getChildAtPosition(MotionEvent ev) { + return getChildCount() > 0 ? getChildAt(0) : null; + } + + @Override + public View getChildContentView(View v) { + return v.findViewById(R.id.call_log_list_item); + } + + @Override + public void onScroll() {} + + @Override + public boolean canChildBeDismissed(View v) { + return true; + } + + @Override + public void onBeginDrag(View v) { + // We do this so the underlying ScrollView knows that it won't get + // the chance to intercept events anymore + requestDisallowInterceptTouchEvent(true); + } + + @Override + public void onChildDismissed(View v) { + if (v != null && mOnItemSwipeListener != null) { + mOnItemSwipeListener.onSwipe(v); + } + } + + @Override + public void onDragCancelled(View v) {} + + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + if (mSwipeHelper != null) { + return mSwipeHelper.onInterceptTouchEvent(ev) || super.onInterceptTouchEvent(ev); + } else { + return super.onInterceptTouchEvent(ev); + } + } + + @Override + public boolean onTouchEvent(MotionEvent ev) { + if (mSwipeHelper != null) { + return mSwipeHelper.onTouchEvent(ev) || super.onTouchEvent(ev); + } else { + return super.onTouchEvent(ev); + } + } + + public void setOnItemSwipeListener(OnItemGestureListener listener) { + mOnItemSwipeListener = listener; + } + } +} diff --git a/src/com/android/dialer/list/SpeedDialFragment.java b/src/com/android/dialer/list/SpeedDialFragment.java new file mode 100644 index 000000000..9de75bb64 --- /dev/null +++ b/src/com/android/dialer/list/SpeedDialFragment.java @@ -0,0 +1,415 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.dialer.list; + +import android.animation.Animator; +import android.animation.AnimatorSet; +import android.animation.ObjectAnimator; +import android.app.Activity; +import android.app.Fragment; +import android.app.LoaderManager; +import android.content.CursorLoader; +import android.content.Loader; +import android.database.Cursor; +import android.graphics.Rect; +import android.net.Uri; +import android.os.Bundle; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewTreeObserver; +import android.widget.AbsListView; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemClickListener; +import android.widget.ImageView; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.RelativeLayout.LayoutParams; + +import com.android.contacts.common.ContactPhotoManager; +import com.android.contacts.common.ContactTileLoaderFactory; +import com.android.contacts.common.list.ContactTileView; +import com.android.contacts.common.list.OnPhoneNumberPickerActionListener; +import com.android.dialer.R; + +import java.util.ArrayList; +import java.util.HashMap; + +/** + * This fragment displays the user's favorite/frequent contacts in a grid. + */ +public class SpeedDialFragment extends Fragment implements OnItemClickListener, + PhoneFavoritesTileAdapter.OnDataSetChangedForAnimationListener { + + /** + * By default, the animation code assumes that all items in a list view are of the same height + * when animating new list items into view (e.g. from the bottom of the screen into view). + * This can cause incorrect translation offsets when a item that is larger or smaller than + * other list item is removed from the list. This key is used to provide the actual height + * of the removed object so that the actual translation appears correct to the user. + */ + private static final long KEY_REMOVED_ITEM_HEIGHT = Long.MAX_VALUE; + + private static final String TAG = SpeedDialFragment.class.getSimpleName(); + private static final boolean DEBUG = false; + + private int mAnimationDuration; + + /** + * Used with LoaderManager. + */ + private static int LOADER_ID_CONTACT_TILE = 1; + + public interface HostInterface { + public void setDragDropController(DragDropController controller); + } + + private class ContactTileLoaderListener implements LoaderManager.LoaderCallbacks { + @Override + public CursorLoader onCreateLoader(int id, Bundle args) { + if (DEBUG) Log.d(TAG, "ContactTileLoaderListener#onCreateLoader."); + return ContactTileLoaderFactory.createStrequentPhoneOnlyLoader(getActivity()); + } + + @Override + public void onLoadFinished(Loader loader, Cursor data) { + if (DEBUG) Log.d(TAG, "ContactTileLoaderListener#onLoadFinished"); + mContactTileAdapter.setContactCursor(data); + setEmptyViewVisibility(mContactTileAdapter.getCount() == 0); + } + + @Override + public void onLoaderReset(Loader loader) { + if (DEBUG) Log.d(TAG, "ContactTileLoaderListener#onLoaderReset. "); + } + } + + private class ContactTileAdapterListener implements ContactTileView.Listener { + @Override + public void onContactSelected(Uri contactUri, Rect targetRect) { + if (mPhoneNumberPickerActionListener != null) { + mPhoneNumberPickerActionListener.onPickPhoneNumberAction(contactUri); + } + } + + @Override + public void onCallNumberDirectly(String phoneNumber) { + if (mPhoneNumberPickerActionListener != null) { + mPhoneNumberPickerActionListener.onCallNumberDirectly(phoneNumber); + } + } + + @Override + public int getApproximateTileWidth() { + return getView().getWidth(); + } + } + + private class ScrollListener implements ListView.OnScrollListener { + @Override + public void onScroll(AbsListView view, + int firstVisibleItem, int visibleItemCount, int totalItemCount) { + if (mActivityScrollListener != null) { + mActivityScrollListener.onListFragmentScroll(firstVisibleItem, visibleItemCount, + totalItemCount); + } + } + + @Override + public void onScrollStateChanged(AbsListView view, int scrollState) { + mActivityScrollListener.onListFragmentScrollStateChange(scrollState); + } + } + + private OnPhoneNumberPickerActionListener mPhoneNumberPickerActionListener; + + private OnListFragmentScrolledListener mActivityScrollListener; + private PhoneFavoritesTileAdapter mContactTileAdapter; + + private View mParentView; + + private PhoneFavoriteListView mListView; + + private View mPhoneFavoritesMenu; + private View mContactTileFrame; + + private TileInteractionTeaserView mTileInteractionTeaserView; + + private final HashMap mItemIdTopMap = new HashMap(); + private final HashMap mItemIdLeftMap = new HashMap(); + + /** + * Layout used when there are no favorites. + */ + private View mEmptyView; + + private final ContactTileView.Listener mContactTileAdapterListener = + new ContactTileAdapterListener(); + private final LoaderManager.LoaderCallbacks mContactTileLoaderListener = + new ContactTileLoaderListener(); + private final ScrollListener mScrollListener = new ScrollListener(); + + @Override + public void onAttach(Activity activity) { + if (DEBUG) Log.d(TAG, "onAttach()"); + super.onAttach(activity); + + // Construct two base adapters which will become part of PhoneFavoriteMergedAdapter. + // We don't construct the resultant adapter at this moment since it requires LayoutInflater + // that will be available on onCreateView(). + mContactTileAdapter = new PhoneFavoritesTileAdapter(activity, mContactTileAdapterListener, + this); + mContactTileAdapter.setPhotoLoader(ContactPhotoManager.getInstance(activity)); + } + + @Override + public void onCreate(Bundle savedState) { + if (DEBUG) Log.d(TAG, "onCreate()"); + super.onCreate(savedState); + + mAnimationDuration = getResources().getInteger(R.integer.fade_duration); + } + + @Override + public void onResume() { + super.onResume(); + + getLoaderManager().getLoader(LOADER_ID_CONTACT_TILE).forceLoad(); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + mParentView = inflater.inflate(R.layout.phone_favorites_fragment, container, false); + + mListView = (PhoneFavoriteListView) mParentView.findViewById(R.id.contact_tile_list); + mListView.setOnItemClickListener(this); + mListView.setVerticalScrollBarEnabled(false); + mListView.setVerticalScrollbarPosition(View.SCROLLBAR_POSITION_RIGHT); + mListView.setScrollBarStyle(ListView.SCROLLBARS_OUTSIDE_OVERLAY); + mListView.getDragDropController().addOnDragDropListener(mContactTileAdapter); + + final ImageView dragShadowOverlay = + (ImageView) mParentView.findViewById(R.id.contact_tile_drag_shadow_overlay); + mListView.setDragShadowOverlay(dragShadowOverlay); + + mEmptyView = mParentView.findViewById(R.id.phone_no_favorites_view); + + mPhoneFavoritesMenu = inflater.inflate(R.layout.phone_favorites_menu, mListView, false); + + mContactTileFrame = mParentView.findViewById(R.id.contact_tile_frame); + + mTileInteractionTeaserView = (TileInteractionTeaserView) inflater.inflate( + R.layout.tile_interactions_teaser_view, mListView, false); + + mListView.setAdapter(mContactTileAdapter); + + mListView.setOnScrollListener(mScrollListener); + mListView.setFastScrollEnabled(false); + mListView.setFastScrollAlwaysVisible(false); + + return mParentView; + } + + public boolean hasFrequents() { + if (mContactTileAdapter == null) return false; + return mContactTileAdapter.getNumFrequents() > 0; + } + + /* package */ void setEmptyViewVisibility(final boolean visible) { + final int previousVisibility = mEmptyView.getVisibility(); + final int newVisibility = visible ? View.VISIBLE : View.GONE; + + if (previousVisibility != newVisibility) { + final RelativeLayout.LayoutParams params = (LayoutParams) mContactTileFrame + .getLayoutParams(); + params.height = visible ? LayoutParams.WRAP_CONTENT : LayoutParams.MATCH_PARENT; + mContactTileFrame.setLayoutParams(params); + mEmptyView.setVisibility(newVisibility); + } + } + + @Override + public void onStart() { + super.onStart(); + + final Activity activity = getActivity(); + + try { + mActivityScrollListener = (OnListFragmentScrolledListener) activity; + } catch (ClassCastException e) { + throw new ClassCastException(activity.toString() + + " must implement OnListFragmentScrolledListener"); + } + + try { + OnDragDropListener listener = (OnDragDropListener) activity; + mListView.getDragDropController().addOnDragDropListener(listener); + ((HostInterface) activity).setDragDropController(mListView.getDragDropController()); + } catch (ClassCastException e) { + throw new ClassCastException(activity.toString() + + " must implement OnDragDropListener and HostInterface"); + } + + try { + mPhoneNumberPickerActionListener = (OnPhoneNumberPickerActionListener) activity; + } catch (ClassCastException e) { + throw new ClassCastException(activity.toString() + + " must implement PhoneFavoritesFragment.listener"); + } + + // Use initLoader() instead of restartLoader() to refraining unnecessary reload. + // This method call implicitly assures ContactTileLoaderListener's onLoadFinished() will + // be called, on which we'll check if "all" contacts should be reloaded again or not. + getLoaderManager().initLoader(LOADER_ID_CONTACT_TILE, null, mContactTileLoaderListener); + } + + /** + * {@inheritDoc} + * + * This is only effective for elements provided by {@link #mContactTileAdapter}. + * {@link #mContactTileAdapter} has its own logic for click events. + */ + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + final int contactTileAdapterCount = mContactTileAdapter.getCount(); + if (position <= contactTileAdapterCount) { + Log.e(TAG, "onItemClick() event for unexpected position. " + + "The position " + position + " is before \"all\" section. Ignored."); + } + } + + /** + * Cache the current view offsets into memory. Once a relayout of views in the ListView + * has happened due to a dataset change, the cached offsets are used to create animations + * that slide views from their previous positions to their new ones, to give the appearance + * that the views are sliding into their new positions. + */ + private void saveOffsets(int removedItemHeight) { + final int firstVisiblePosition = mListView.getFirstVisiblePosition(); + if (DEBUG) { + Log.d(TAG, "Child count : " + mListView.getChildCount()); + } + for (int i = 0; i < mListView.getChildCount(); i++) { + final View child = mListView.getChildAt(i); + final int position = firstVisiblePosition + i; + final long itemId = mContactTileAdapter.getItemId(position); + if (DEBUG) { + Log.d(TAG, "Saving itemId: " + itemId + " for listview child " + i + " Top: " + + child.getTop()); + } + mItemIdTopMap.put(itemId, child.getTop()); + mItemIdLeftMap.put(itemId, child.getLeft()); + } + + mItemIdTopMap.put(KEY_REMOVED_ITEM_HEIGHT, removedItemHeight); + } + + /* + * Performs animations for the gridView + */ + private void animateGridView(final long... idsInPlace) { + if (mItemIdTopMap.isEmpty()) { + // Don't do animations if the database is being queried for the first time and + // the previous item offsets have not been cached, or the user hasn't done anything + // (dragging, swiping etc) that requires an animation. + return; + } + + final ViewTreeObserver observer = mListView.getViewTreeObserver(); + observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { + @SuppressWarnings("unchecked") + @Override + public boolean onPreDraw() { + observer.removeOnPreDrawListener(this); + final int firstVisiblePosition = mListView.getFirstVisiblePosition(); + final AnimatorSet animSet = new AnimatorSet(); + final ArrayList animators = new ArrayList(); + for (int i = 0; i < mListView.getChildCount(); i++) { + final View child = mListView.getChildAt(i); + int position = firstVisiblePosition + i; + + final long itemId = mContactTileAdapter.getItemId(position); + + if (containsId(idsInPlace, itemId)) { + animators.add(ObjectAnimator.ofFloat( + child, "alpha", 0.0f, 1.0f)); + break; + } else { + Integer startTop = mItemIdTopMap.get(itemId); + Integer startLeft = mItemIdLeftMap.get(itemId); + final int top = child.getTop(); + final int left = child.getLeft(); + int deltaX = 0; + int deltaY = 0; + + if (startLeft != null) { + if (startLeft != left) { + deltaX = startLeft - left; + animators.add(ObjectAnimator.ofFloat( + child, "translationX", deltaX, 0.0f)); + } + } + + if (startTop != null) { + if (startTop != top) { + deltaY = startTop - top; + animators.add(ObjectAnimator.ofFloat( + child, "translationY", deltaY, 0.0f)); + } + } + + if (DEBUG) { + Log.d(TAG, "Found itemId: " + itemId + " for listview child " + i + + " Top: " + top + + " Delta: " + deltaY); + } + } + } + + if (animators.size() > 0) { + animSet.setDuration(mAnimationDuration).playTogether(animators); + animSet.start(); + } + + mItemIdTopMap.clear(); + mItemIdLeftMap.clear(); + return true; + } + }); + } + + private boolean containsId(long[] ids, long target) { + // Linear search on array is fine because this is typically only 0-1 elements long + for (int i = 0; i < ids.length; i++) { + if (ids[i] == target) { + return true; + } + } + return false; + } + + @Override + public void onDataSetChangedForAnimation(long... idsInPlace) { + animateGridView(idsInPlace); + } + + @Override + public void cacheOffsetsForDatasetChange() { + saveOffsets(0); + } +} diff --git a/src/com/android/dialer/list/TileInteractionTeaserView.java b/src/com/android/dialer/list/TileInteractionTeaserView.java index 6e70fd186..fd5ed3425 100644 --- a/src/com/android/dialer/list/TileInteractionTeaserView.java +++ b/src/com/android/dialer/list/TileInteractionTeaserView.java @@ -31,7 +31,7 @@ public class TileInteractionTeaserView extends FrameLayout { private int mTextTop; private int mAnimatedHeight = -1; - private PhoneFavoriteMergedAdapter mAdapter; + private ShortcutCardsAdapter mAdapter; public TileInteractionTeaserView(final Context context) { this(context, null); @@ -91,7 +91,7 @@ public class TileInteractionTeaserView extends FrameLayout { return prefs.getBoolean(KEY_TILE_INTERACTION_TEASER_SHOWN, true); } - public void setAdapter(PhoneFavoriteMergedAdapter adapter) { + public void setAdapter(ShortcutCardsAdapter adapter) { mAdapter = adapter; } -- cgit v1.2.3