From 4cde566de5f54b6bdd305229c3134068cdde4bbd Mon Sep 17 00:00:00 2001 From: Yorke Lee Date: Fri, 18 Apr 2014 17:14:58 -0700 Subject: Move call shortcut cards to their own list This CL migrates the logic that queries for and displays call shortcut cards to ListsFragment so that they can be displayed above the main contacts viewpager. * Add a ListView above the ViewPager in ListsFragment * Implement CallLogQueryHandler.Listener and CallLogAdapter.CallFetcher in ListsFragment, and delete that corresponding logic in PhoneFavoritesFragment. * Use animateLayoutChanges on the parent LinearLayout hosting shortcard cards so that we don't have to handle animations ourselves when a card is swiped away. * Make the minimum set of changes to PhoneFavoritesMergedAdapter so that only call shortcut cards are displayed (no more menu, teaser, etc). More significant changes to actually delete unnecessary logic is upcoming in a separate CL. Bug: 13963734 Change-Id: I55cdc53a9311b1bb78422aab9d174e860596b997 --- res/layout/call_log_list_item.xml | 2 +- res/layout/lists_fragment.xml | 9 ++ res/layout/phone_favorites_fragment.xml | 1 + src/com/android/dialer/list/ListsFragment.java | 158 +++++++++++++++++++-- .../android/dialer/list/PhoneFavoriteFragment.java | 114 --------------- .../dialer/list/PhoneFavoriteMergedAdapter.java | 28 +--- 6 files changed, 166 insertions(+), 146 deletions(-) diff --git a/res/layout/call_log_list_item.xml b/res/layout/call_log_list_item.xml index a33ec7d7c..953efc403 100644 --- a/res/layout/call_log_list_item.xml +++ b/res/layout/call_log_list_item.xml @@ -38,6 +38,7 @@ @@ -48,7 +49,6 @@ android:layout_width="0dp" android:layout_weight="1" android:layout_height="wrap_content" - android:layout_centerVertical="true" android:padding="@dimen/call_log_outer_margin" android:orientation="horizontal" android:gravity="center_vertical" diff --git a/res/layout/lists_fragment.xml b/res/layout/lists_fragment.xml index 740dc2af6..6ed0f856e 100644 --- a/res/layout/lists_fragment.xml +++ b/res/layout/lists_fragment.xml @@ -19,7 +19,16 @@ android:layout_height="match_parent" android:paddingTop="?android:attr/actionBarSize" android:orientation="vertical" + android:animateLayoutChanges="true" android:id="@+id/lists_frame"> + { + + @Override + public Loader onCreateLoader(int id, Bundle args) { + final Uri uri = CallLog.Calls.CONTENT_URI; + final String[] projection = new String[] {CallLog.Calls.TYPE}; + final String selection = CallLog.Calls.TYPE + " = " + CallLog.Calls.MISSED_TYPE + + " AND " + CallLog.Calls.IS_READ + " = 0"; + return new CursorLoader(getActivity(), uri, projection, selection, null, null); + } + + @Override + public void onLoadFinished(Loader cursorLoader, Cursor data) { + mCallLogAdapter.setMissedCalls(data); + } + + @Override + public void onLoaderReset(Loader cursorLoader) { + } + } public class ViewPagerAdapter extends FragmentPagerAdapter { public ViewPagerAdapter(FragmentManager fm) { @@ -75,6 +133,45 @@ public class ListsFragment extends Fragment { } } + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + mCallLogQueryHandler = new CallLogQueryHandler(getActivity().getContentResolver(), + this, 1); + final String currentCountryIso = GeoUtil.getCurrentCountryIso(getActivity()); + mCallLogAdapter = ObjectFactory.newCallLogAdapter(getActivity(), this, + new ContactInfoHelper(getActivity(), currentCountryIso), false, false); + + mMergedAdapter = new PhoneFavoriteMergedAdapter(getActivity(), this, null, + mCallLogAdapter, null, null); + } + + @Override + public void onStart() { + super.onStart(); + getLoaderManager().initLoader(MISSED_CALL_LOADER, null, new MissedCallLogLoaderListener()); + } + + @Override + public void onResume() { + super.onResume(); + final SharedPreferences prefs = getActivity().getSharedPreferences( + DialtactsActivity.SHARED_PREFS_NAME, Context.MODE_PRIVATE); + mLastCallShortcutDate = prefs.getLong(KEY_LAST_DISMISSED_CALL_SHORTCUT_DATE, 0); + + fetchCalls(); + mCallLogAdapter.setLoading(true); + } + + @Override + public void onPause() { + // Wipe the cache to refresh the call shortcut item. This is not that expensive because + // it only contains one item. + mCallLogAdapter.invalidateCache(); + super.onPause(); + } + @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { @@ -91,6 +188,47 @@ public class ListsFragment extends Fragment { ViewPagerTabs tabs = (ViewPagerTabs) parentView.findViewById(R.id.lists_pager_header); tabs.setViewPager(mViewPager); + + final ListView shortcutCardsListView = + (ListView) parentView.findViewById(R.id.shortcut_card_list); + shortcutCardsListView.setAdapter(mMergedAdapter); + + LayoutTransition transition = ((LinearLayout) parentView).getLayoutTransition(); + // Turns on animations for all types of layout changes so that they occur for + // height changes. + transition.enableTransitionType(LayoutTransition.CHANGING); return parentView; } + + @Override + public void onVoicemailStatusFetched(Cursor statusCursor) { + // no-op + } + + @Override + public void onCallsFetched(Cursor cursor) { + mCallLogAdapter.setLoading(false); + + // Save the date of the most recent call log item + if (cursor != null && cursor.moveToFirst()) { + mCurrentCallShortcutDate = cursor.getLong(CallLogQuery.DATE); + } + + mCallLogAdapter.changeCursor(cursor); + mMergedAdapter.notifyDataSetChanged(); + } + + @Override + public void fetchCalls() { + mCallLogQueryHandler.fetchCalls(CallLogQueryHandler.CALL_TYPE_ALL, mLastCallShortcutDate); + } + + public void dismissShortcut(View view) { + mLastCallShortcutDate = mCurrentCallShortcutDate; + final SharedPreferences prefs = view.getContext().getSharedPreferences( + DialtactsActivity.SHARED_PREFS_NAME, Context.MODE_PRIVATE); + prefs.edit().putLong(KEY_LAST_DISMISSED_CALL_SHORTCUT_DATE, mLastCallShortcutDate) + .apply(); + fetchCalls(); + } } diff --git a/src/com/android/dialer/list/PhoneFavoriteFragment.java b/src/com/android/dialer/list/PhoneFavoriteFragment.java index ed6b5c810..05e2d44d4 100644 --- a/src/com/android/dialer/list/PhoneFavoriteFragment.java +++ b/src/com/android/dialer/list/PhoneFavoriteFragment.java @@ -21,25 +21,20 @@ import android.animation.ObjectAnimator; import android.app.Activity; import android.app.Fragment; import android.app.LoaderManager; -import android.content.Context; import android.content.CursorLoader; import android.content.Loader; -import android.content.SharedPreferences; import android.database.Cursor; import android.graphics.Rect; import android.net.Uri; import android.os.Bundle; -import android.provider.CallLog; import android.util.Log; import android.view.LayoutInflater; import android.view.View; -import android.view.View.OnClickListener; import android.view.ViewGroup; import android.view.ViewTreeObserver; import android.widget.AbsListView; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; -import android.widget.Button; import android.widget.ImageView; import android.widget.ListView; import android.widget.RelativeLayout; @@ -47,17 +42,9 @@ import android.widget.RelativeLayout.LayoutParams; import com.android.contacts.common.ContactPhotoManager; import com.android.contacts.common.ContactTileLoaderFactory; -import com.android.contacts.common.GeoUtil; -import com.android.contacts.common.list.ContactEntry; import com.android.contacts.common.list.ContactTileView; import com.android.contacts.common.list.OnPhoneNumberPickerActionListener; -import com.android.dialer.DialtactsActivity; import com.android.dialer.R; -import com.android.dialer.calllog.CallLogAdapter; -import com.android.dialer.calllog.CallLogQuery; -import com.android.dialer.calllog.CallLogQueryHandler; -import com.android.dialer.calllog.ContactInfoHelper; -import com.android.dialerbind.ObjectFactory; import java.util.ArrayList; import java.util.HashMap; @@ -71,7 +58,6 @@ import java.util.HashMap; * A contact filter header is also inserted between those adapters' results. */ public class PhoneFavoriteFragment extends Fragment implements OnItemClickListener, - CallLogQueryHandler.Listener, CallLogAdapter.CallFetcher, PhoneFavoritesTileAdapter.OnDataSetChangedForAnimationListener { /** @@ -92,36 +78,11 @@ public class PhoneFavoriteFragment extends Fragment implements OnItemClickListen * Used with LoaderManager. */ private static int LOADER_ID_CONTACT_TILE = 1; - private static int MISSED_CALL_LOADER = 2; - - private static final String KEY_LAST_DISMISSED_CALL_SHORTCUT_DATE = - "key_last_dismissed_call_shortcut_date"; public interface HostInterface { public void setDragDropController(DragDropController controller); } - private class MissedCallLogLoaderListener implements LoaderManager.LoaderCallbacks { - - @Override - public Loader onCreateLoader(int id, Bundle args) { - final Uri uri = CallLog.Calls.CONTENT_URI; - final String[] projection = new String[] {CallLog.Calls.TYPE}; - final String selection = CallLog.Calls.TYPE + " = " + CallLog.Calls.MISSED_TYPE + - " AND " + CallLog.Calls.IS_READ + " = 0"; - return new CursorLoader(getActivity(), uri, projection, selection, null, null); - } - - @Override - public void onLoadFinished(Loader cursorLoader, Cursor data) { - mCallLogAdapter.setMissedCalls(data); - } - - @Override - public void onLoaderReset(Loader cursorLoader) { - } - } - private class ContactTileLoaderListener implements LoaderManager.LoaderCallbacks { @Override public CursorLoader onCreateLoader(int id, Bundle args) { @@ -182,12 +143,8 @@ public class PhoneFavoriteFragment extends Fragment implements OnItemClickListen private OnPhoneNumberPickerActionListener mPhoneNumberPickerActionListener; private OnListFragmentScrolledListener mActivityScrollListener; - private PhoneFavoriteMergedAdapter mAdapter; private PhoneFavoritesTileAdapter mContactTileAdapter; - private CallLogAdapter mCallLogAdapter; - private CallLogQueryHandler mCallLogQueryHandler; - private View mParentView; private PhoneFavoriteListView mListView; @@ -205,17 +162,6 @@ public class PhoneFavoriteFragment extends Fragment implements OnItemClickListen */ private View mEmptyView; - /** - * Call shortcuts older than this date (persisted in shared preferences) will not show up in - * at the top of the screen - */ - private long mLastCallShortcutDate = 0; - - /** - * The date of the current call shortcut that is showing on screen. - */ - private long mCurrentCallShortcutDate = 0; - private final ContactTileView.Listener mContactTileAdapterListener = new ContactTileAdapterListener(); private final LoaderManager.LoaderCallbacks mContactTileLoaderListener = @@ -241,23 +187,12 @@ public class PhoneFavoriteFragment extends Fragment implements OnItemClickListen super.onCreate(savedState); mAnimationDuration = getResources().getInteger(R.integer.fade_duration); - mCallLogQueryHandler = new CallLogQueryHandler(getActivity().getContentResolver(), - this, 1); - final String currentCountryIso = GeoUtil.getCurrentCountryIso(getActivity()); - mCallLogAdapter = ObjectFactory.newCallLogAdapter(getActivity(), this, - new ContactInfoHelper(getActivity(), currentCountryIso), false, false); } @Override public void onResume() { super.onResume(); - final SharedPreferences prefs = getActivity().getSharedPreferences( - DialtactsActivity.SHARED_PREFS_NAME, Context.MODE_PRIVATE); - - mLastCallShortcutDate = prefs.getLong(KEY_LAST_DISMISSED_CALL_SHORTCUT_DATE, 0); - fetchCalls(); - mCallLogAdapter.setLoading(true); getLoaderManager().getLoader(LOADER_ID_CONTACT_TILE).forceLoad(); } @@ -286,12 +221,6 @@ public class PhoneFavoriteFragment extends Fragment implements OnItemClickListen mTileInteractionTeaserView = (TileInteractionTeaserView) inflater.inflate( R.layout.tile_interactions_teaser_view, mListView, false); - mAdapter = new PhoneFavoriteMergedAdapter(getActivity(), this, mContactTileAdapter, - mCallLogAdapter, mPhoneFavoritesMenu, mTileInteractionTeaserView); - - - mTileInteractionTeaserView.setAdapter(mAdapter); - mListView.setAdapter(mContactTileAdapter); mListView.setOnScrollListener(mScrollListener); @@ -352,7 +281,6 @@ public class PhoneFavoriteFragment extends Fragment implements OnItemClickListen // 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); - getLoaderManager().initLoader(MISSED_CALL_LOADER, null, new MissedCallLogLoaderListener()); } /** @@ -370,37 +298,6 @@ public class PhoneFavoriteFragment extends Fragment implements OnItemClickListen } } - @Override - public void onVoicemailStatusFetched(Cursor statusCursor) { - // no-op - } - - @Override - public void onCallsFetched(Cursor cursor) { - mCallLogAdapter.setLoading(false); - - // Save the date of the most recent call log item - if (cursor != null && cursor.moveToFirst()) { - mCurrentCallShortcutDate = cursor.getLong(CallLogQuery.DATE); - } - - mCallLogAdapter.changeCursor(cursor); - mAdapter.notifyDataSetChanged(); - } - - @Override - public void fetchCalls() { - mCallLogQueryHandler.fetchCalls(CallLogQueryHandler.CALL_TYPE_ALL, mLastCallShortcutDate); - } - - @Override - public void onPause() { - // Wipe the cache to refresh the call shortcut item. This is not that expensive because - // it only contains one item. - mCallLogAdapter.invalidateCache(); - super.onPause(); - } - /** * 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 @@ -520,15 +417,4 @@ public class PhoneFavoriteFragment extends Fragment implements OnItemClickListen public void cacheOffsetsForDatasetChange() { saveOffsets(0); } - - public void dismissShortcut(View view) { - final int height = ((View) view.getParent()).getHeight(); - saveOffsets(height); - mLastCallShortcutDate = mCurrentCallShortcutDate; - final SharedPreferences prefs = view.getContext().getSharedPreferences( - DialtactsActivity.SHARED_PREFS_NAME, Context.MODE_PRIVATE); - prefs.edit().putLong(KEY_LAST_DISMISSED_CALL_SHORTCUT_DATE, mLastCallShortcutDate) - .apply(); - fetchCalls(); - } } diff --git a/src/com/android/dialer/list/PhoneFavoriteMergedAdapter.java b/src/com/android/dialer/list/PhoneFavoriteMergedAdapter.java index e2b9bb2bf..03ff67ea1 100644 --- a/src/com/android/dialer/list/PhoneFavoriteMergedAdapter.java +++ b/src/com/android/dialer/list/PhoneFavoriteMergedAdapter.java @@ -55,7 +55,7 @@ public class PhoneFavoriteMergedAdapter extends BaseAdapter { private final PhoneFavoritesTileAdapter mContactTileAdapter; private final CallLogAdapter mCallLogAdapter; private final View mPhoneFavoritesMenu; - private final PhoneFavoriteFragment mFragment; + private final ListsFragment mFragment; private final TileInteractionTeaserView mTileInteractionTeaserView; private final int mCallLogPadding; @@ -100,7 +100,7 @@ public class PhoneFavoriteMergedAdapter extends BaseAdapter { }; public PhoneFavoriteMergedAdapter(Context context, - PhoneFavoriteFragment fragment, + ListsFragment fragment, PhoneFavoritesTileAdapter contactTileAdapter, CallLogAdapter callLogAdapter, View phoneFavoritesMenu, @@ -113,11 +113,7 @@ public class PhoneFavoriteMergedAdapter extends BaseAdapter { mCallLogAdapter = callLogAdapter; mObserver = new CustomDataSetObserver(); mCallLogAdapter.registerDataSetObserver(mObserver); - mContactTileAdapter.registerDataSetObserver(mObserver); mPhoneFavoritesMenu = phoneFavoritesMenu; - // Temporary hack to hide the favorites menu because it is not being used. - // It should be removed from this adapter entirely eventually. - mPhoneFavoritesMenu.setVisibility(View.GONE); mTileInteractionTeaserView = tileInteractionTeaserView; mCallLogQueryHandler = new CallLogQueryHandler(mContext.getContentResolver(), mCallLogQueryHandlerListener); @@ -133,8 +129,7 @@ public class PhoneFavoriteMergedAdapter extends BaseAdapter { */ @Override public int getCount() { - return mContactTileAdapter.getCount() + mCallLogAdapter.getCount() + getTeaserViewCount() - + 1; + return mCallLogAdapter.getCount(); } @Override @@ -196,10 +191,7 @@ public class PhoneFavoriteMergedAdapter extends BaseAdapter { */ @Override public int getViewTypeCount() { - return (mContactTileAdapter.getViewTypeCount() + /* Favorite and frequent */ - mCallLogAdapter.getViewTypeCount() + /* Recent call log */ - getTeaserViewCount() + /* Teaser */ - 1); /* Favorites menu. */ + return mCallLogAdapter.getViewTypeCount(); } @Override @@ -207,9 +199,7 @@ public class PhoneFavoriteMergedAdapter extends BaseAdapter { final int callLogAdapterCount = mCallLogAdapter.getCount(); if (position < callLogAdapterCount) { - // View type of the call log adapter is the last view type of the contact tile adapter - // + 1 - return mContactTileAdapter.getViewTypeCount(); + return 0; } else if (position == TILE_INTERACTION_TEASER_VIEW_POSITION + callLogAdapterCount && mTileInteractionTeaserView.getShouldDisplayInList()) { // View type of the teaser row is the last view type of the contact tile adapter +2 @@ -236,11 +226,7 @@ public class PhoneFavoriteMergedAdapter extends BaseAdapter { public View getView(int position, View convertView, ViewGroup parent) { final int callLogAdapterCount = mCallLogAdapter.getCount(); - // Get the view for the "teaser view" which describes how to re-arrange favorites. - if (mTileInteractionTeaserView.getShouldDisplayInList() - && position == TILE_INTERACTION_TEASER_VIEW_POSITION + callLogAdapterCount) { - return mTileInteractionTeaserView; - } else if (callLogAdapterCount > 0 && position < callLogAdapterCount) { + if (callLogAdapterCount > 0 && position < callLogAdapterCount) { // Handle case where we are requesting the view for the "most recent caller". final SwipeableCallLogRow wrapper; @@ -281,7 +267,7 @@ public class PhoneFavoriteMergedAdapter extends BaseAdapter { @Override public boolean areAllItemsEnabled() { - return mCallLogAdapter.areAllItemsEnabled() && mContactTileAdapter.areAllItemsEnabled(); + return mCallLogAdapter.areAllItemsEnabled(); } @Override -- cgit v1.2.3