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
diff --git a/res/layout/call_log_list_item.xml b/res/layout/call_log_list_item.xml
index a33ec7d..953efc4 100644
--- a/res/layout/call_log_list_item.xml
+++ b/res/layout/call_log_list_item.xml
@@ -38,6 +38,7 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:baselineAligned="false"
android:orientation="horizontal"
android:gravity="center_vertical"
>
@@ -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 740dc2a..6ed0f85 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">
+ <ListView
+ android:id="@+id/shortcut_card_list"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="@color/actionbar_background_color"
+ android:clipToPadding="false"
+ android:fadingEdge="none"
+ android:divider="@null" />
<com.android.dialer.list.ViewPagerTabs
android:id="@+id/lists_pager_header"
android:layout_width="match_parent"
diff --git a/res/layout/phone_favorites_fragment.xml b/res/layout/phone_favorites_fragment.xml
index 5e9e3bb..89a9f73 100644
--- a/res/layout/phone_favorites_fragment.xml
+++ b/res/layout/phone_favorites_fragment.xml
@@ -35,6 +35,7 @@
android:id="@+id/contact_tile_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:paddingTop="@dimen/favorites_row_top_padding"
android:numColumns="@integer/contact_tile_column_count_in_favorites"
android:clipToPadding="false"
android:fadingEdge="none"
diff --git a/src/com/android/dialer/list/ListsFragment.java b/src/com/android/dialer/list/ListsFragment.java
index 5132727..3144b86 100644
--- a/src/com/android/dialer/list/ListsFragment.java
+++ b/src/com/android/dialer/list/ListsFragment.java
@@ -1,19 +1,34 @@
package com.android.dialer.list;
-import android.app.Activity;
+import android.animation.LayoutTransition;
import android.app.Fragment;
import android.app.FragmentManager;
+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.net.Uri;
import android.os.Bundle;
+import android.provider.CallLog;
import android.support.v13.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.LinearLayout;
+import android.widget.ListView;
-import com.android.contacts.common.list.OnPhoneNumberPickerActionListener;
+import com.android.contacts.common.GeoUtil;
+import com.android.dialer.DialtactsActivity;
import com.android.dialer.R;
+import com.android.dialer.calllog.CallLogAdapter;
import com.android.dialer.calllog.CallLogFragment;
+import com.android.dialer.calllog.CallLogQuery;
import com.android.dialer.calllog.CallLogQueryHandler;
+import com.android.dialer.calllog.ContactInfoHelper;
+import com.android.dialerbind.ObjectFactory;
/**
* Fragment that is used as the main screen of the Dialer.
@@ -23,7 +38,23 @@
* ViewPager containing the lists up above the shortcut cards and pin it against the top of the
* screen.
*/
-public class ListsFragment extends Fragment {
+public class ListsFragment extends Fragment implements CallLogQueryHandler.Listener,
+ CallLogAdapter.CallFetcher {
+
+ private static final int TAB_INDEX_SPEED_DIAL = 0;
+ private static final int TAB_INDEX_RECENTS = 1;
+ private static final int TAB_INDEX_ALL_CONTACTS = 2;
+
+ private static final int TAB_INDEX_COUNT = 3;
+
+ // TODO: Replace with a date limit (e.g. 2 weeks)
+ private static final int MAX_ENTRIES = 20;
+
+ private static final String KEY_LAST_DISMISSED_CALL_SHORTCUT_DATE =
+ "key_last_dismissed_call_shortcut_date";
+
+ // Used with LoaderManager
+ private static int MISSED_CALL_LOADER = 1;
private ViewPager mViewPager;
private ViewPagerAdapter mViewPagerAdapter;
@@ -31,16 +62,43 @@
private CallLogFragment mRecentsFragment;
private AllContactsFragment mAllContactsFragment;
- private static final int TAB_INDEX_SPEED_DIAL = 0;
- private static final int TAB_INDEX_RECENTS = 1;
- private static final int TAB_INDEX_ALL_CONTACTS = 2;
-
private String[] mTabTitles;
- private static final int TAB_INDEX_COUNT = 3;
+ private PhoneFavoriteMergedAdapter mMergedAdapter;
+ private CallLogAdapter mCallLogAdapter;
+ private CallLogQueryHandler mCallLogQueryHandler;
- // TODO: Replace with a date limit (e.g. 2 weeks)
- private static final int MAX_ENTRIES = 20;
+ /**
+ * 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 class MissedCallLogLoaderListener implements LoaderManager.LoaderCallbacks<Cursor> {
+
+ @Override
+ public Loader<Cursor> 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<Cursor> cursorLoader, Cursor data) {
+ mCallLogAdapter.setMissedCalls(data);
+ }
+
+ @Override
+ public void onLoaderReset(Loader<Cursor> cursorLoader) {
+ }
+ }
public class ViewPagerAdapter extends FragmentPagerAdapter {
public ViewPagerAdapter(FragmentManager fm) {
@@ -76,6 +134,45 @@
}
@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) {
final View parentView = inflater.inflate(R.layout.lists_fragment, container, false);
@@ -91,6 +188,47 @@
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 ed6b5c8..05e2d44 100644
--- a/src/com/android/dialer/list/PhoneFavoriteFragment.java
+++ b/src/com/android/dialer/list/PhoneFavoriteFragment.java
@@ -21,25 +21,20 @@
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 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 @@
* 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 @@
* 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<Cursor> {
-
- @Override
- public Loader<Cursor> 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<Cursor> cursorLoader, Cursor data) {
- mCallLogAdapter.setMissedCalls(data);
- }
-
- @Override
- public void onLoaderReset(Loader<Cursor> cursorLoader) {
- }
- }
-
private class ContactTileLoaderListener implements LoaderManager.LoaderCallbacks<Cursor> {
@Override
public CursorLoader onCreateLoader(int id, Bundle args) {
@@ -182,12 +143,8 @@
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 @@
*/
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<Cursor> mContactTileLoaderListener =
@@ -241,23 +187,12 @@
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 @@
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 @@
// 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 @@
}
}
- @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 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 e2b9bb2..03ff67e 100644
--- a/src/com/android/dialer/list/PhoneFavoriteMergedAdapter.java
+++ b/src/com/android/dialer/list/PhoneFavoriteMergedAdapter.java
@@ -55,7 +55,7 @@
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 PhoneFavoriteMergedAdapter(Context context,
- PhoneFavoriteFragment fragment,
+ ListsFragment fragment,
PhoneFavoritesTileAdapter contactTileAdapter,
CallLogAdapter callLogAdapter,
View phoneFavoritesMenu,
@@ -113,11 +113,7 @@
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 @@
*/
@Override
public int getCount() {
- return mContactTileAdapter.getCount() + mCallLogAdapter.getCount() + getTeaserViewCount()
- + 1;
+ return mCallLogAdapter.getCount();
}
@Override
@@ -196,10 +191,7 @@
*/
@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 @@
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 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 @@
@Override
public boolean areAllItemsEnabled() {
- return mCallLogAdapter.areAllItemsEnabled() && mContactTileAdapter.areAllItemsEnabled();
+ return mCallLogAdapter.areAllItemsEnabled();
}
@Override