ListsFragment.java revision bcb91d9c9539e03fdaec74bb38acecdd34552257
1619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeypackage com.android.dialer.list; 2619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 3619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.animation.LayoutTransition; 4619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.app.ActionBar; 5619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.app.Fragment; 6619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.app.FragmentManager; 7619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.app.LoaderManager; 8619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.content.Context; 9619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.content.CursorLoader; 10619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.content.Loader; 11619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.content.SharedPreferences; 12619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.database.Cursor; 13619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.graphics.Rect; 14619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.net.Uri; 15619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.os.Bundle; 16619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.provider.CallLog; 1728f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millarimport android.support.v13.app.FragmentPagerAdapter; 18619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.support.v4.view.ViewPager; 19bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikovimport android.support.v4.view.ViewPager.OnPageChangeListener; 20bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikovimport android.util.Log; 21bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikovimport android.view.LayoutInflater; 22bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikovimport android.view.View; 23bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikovimport android.view.ViewGroup; 24bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikovimport android.widget.ListView; 25bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 26b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onukiimport com.android.contacts.common.GeoUtil; 27bee1a6b2e7cbea778195890e442c9e50f2a4e6d9Dmitri Plotnikovimport com.android.dialer.DialtactsActivity; 28e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov 29ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.view.View.OnClickListener; 30ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 31619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport com.android.dialer.R; 329701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onukiimport com.android.dialer.calllog.CallLogAdapter; 330bdbe752c3c0cbbef2acb4eca74642aec9195d88Makoto Onukiimport com.android.dialer.calllog.CallLogFragment; 3435997f3fdee2984b6d5373326110eda26929001aMakoto Onukiimport com.android.dialer.calllog.CallLogQuery; 35619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport com.android.dialer.calllog.CallLogQueryHandler; 36619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport com.android.dialer.calllog.ContactInfoHelper; 3772e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikovimport com.android.dialer.list.ShortcutCardsAdapter.SwipeableShortcutCard; 38b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onukiimport com.android.dialer.widget.OverlappingPaneLayout; 395dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikovimport com.android.dialer.widget.OverlappingPaneLayout.PanelSlideListener; 40b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikovimport com.android.dialerbind.ObjectFactory; 41ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 4289b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikovimport java.util.ArrayList; 4389b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov 4489b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov/** 45ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey * Fragment that is used as the main screen of the Dialer. 46b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki * 47bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov * Contains a ViewPager that contains various contact lists like the Speed Dial list and the 48b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki * All Contacts list. This will also eventually contain the logic that allows sliding the 4989b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov * ViewPager containing the lists up above the shortcut cards and pin it against the top of the 50b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki * screen. 51b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki */ 52ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeypublic class ListsFragment extends Fragment implements CallLogQueryHandler.Listener, 53619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey CallLogAdapter.CallFetcher, ViewPager.OnPageChangeListener { 5447fd3881dfd2a21de29e917b6114974ff0a67b1bDmitri Plotnikov 55ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final boolean DEBUG = DialtactsActivity.DEBUG; 5689b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov private static final String TAG = "ListsFragment"; 5789b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov 58e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov public static final int TAB_INDEX_SPEED_DIAL = 0; 59ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey public static final int TAB_INDEX_RECENTS = 1; 60e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov public static final int TAB_INDEX_ALL_CONTACTS = 2; 611d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey 62619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey private static final int TAB_INDEX_COUNT = 3; 63619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 64619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey private static final int MAX_RECENTS_ENTRIES = 20; 65619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // Oldest recents entry to display is 2 weeks old. 669701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki private static final long OLDEST_RECENTS_DATE = 1000L * 60 * 60 * 24 * 14; 67619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 68400e50c1efeb601f6162bd829fdf33e9dc5252f6Makoto Onuki private static final String KEY_LAST_DISMISSED_CALL_SHORTCUT_DATE = 6938210445730ee04c351c7cc1b3800cfe23e34325Makoto Onuki "key_last_dismissed_call_shortcut_date"; 703a219cc3f5045bdebfcd975bf857c6ff26886a22Yorke Lee 7138210445730ee04c351c7cc1b3800cfe23e34325Makoto Onuki public static final float REMOVE_VIEW_SHOWN_ALPHA = 0.5f; 7238210445730ee04c351c7cc1b3800cfe23e34325Makoto Onuki public static final float REMOVE_VIEW_HIDDEN_ALPHA = 1; 73f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 74bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov // Used with LoaderManager 75b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki private static int MISSED_CALL_LOADER = 1; 7624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 77b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki public interface HostInterface { 785dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public void showCallHistory(); 7924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro public int getActionBarHeight(); 80619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 81619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 82619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey private ActionBar mActionBar; 83619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey private ViewPager mViewPager; 84619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey private ViewPagerTabs mViewPagerTabs; 85619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey private ViewPagerAdapter mViewPagerAdapter; 86619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey private ListView mShortcutCardsListView; 87619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey private RemoveView mRemoveView; 88619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey private View mRemoveViewContent; 89619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey private SpeedDialFragment mSpeedDialFragment; 90619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey private CallLogFragment mRecentsFragment; 91619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey private AllContactsFragment mAllContactsFragment; 92619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey private ArrayList<OnPageChangeListener> mOnPageChangeListeners = 93619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey new ArrayList<OnPageChangeListener>(); 94619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 95619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey private String[] mTabTitles; 96619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 97619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey private ShortcutCardsAdapter mMergedAdapter; 98bee1a6b2e7cbea778195890e442c9e50f2a4e6d9Dmitri Plotnikov private CallLogAdapter mCallLogAdapter; 9989b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov private CallLogQueryHandler mCallLogQueryHandler; 10089b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov 101bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov private boolean mIsPanelOpen = true; 102bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 10324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro /** 104eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee * Call shortcuts older than this date (persisted in shared preferences) will not show up in 10524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro * at the top of the screen 10689b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov */ 10789b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov private long mLastCallShortcutDate = 0; 10889b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov 10989b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov /** 11089b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov * The date of the current call shortcut that is showing on screen. 11189b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov */ 11289b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov private long mCurrentCallShortcutDate = 0; 11389b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov 11489b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov private class MissedCallLogLoaderListener implements LoaderManager.LoaderCallbacks<Cursor> { 11589b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov 116619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey @Override 117bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov public Loader<Cursor> onCreateLoader(int id, Bundle args) { 118bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov final Uri uri = CallLog.Calls.CONTENT_URI; 119bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov final String[] projection = new String[] {CallLog.Calls.TYPE}; 120bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov final String selection = CallLog.Calls.TYPE + " = " + CallLog.Calls.MISSED_TYPE + 121bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov " AND " + CallLog.Calls.IS_READ + " = 0"; 122bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov return new CursorLoader(getActivity(), uri, projection, selection, null, null); 123bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 124bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 125bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov @Override 126bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor data) { 127bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mCallLogAdapter.setMissedCalls(data); 128bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 129bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 130bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov @Override 131bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov public void onLoaderReset(Loader<Cursor> cursorLoader) { 132bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 133bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 134bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 135bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov private PanelSlideListener mPanelSlideListener = new PanelSlideListener() { 136bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov @Override 137bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov public void onPanelSlide(View panel, float slideOffset) { 138bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov // For every 1 percent that the panel is slid upwards, clip 1.5 percent from each edge 139bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov // of the shortcut card, to achieve the animated effect of the shortcut card 140bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov // rapidly shrinking and disappearing from view when the panel is slid upwards. 141bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov // slideOffset is 1 when the shortcut card is fully exposed, and 0 when completely 142bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov // hidden. 143bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov float ratioCardHidden = (1 - slideOffset) * 1.5f; 144bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov if (mShortcutCardsListView.getCount() > 0) { 145bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov SwipeableShortcutCard v = 146bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov (SwipeableShortcutCard) mShortcutCardsListView.getChildAt(0); 147bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov v.clipCard(ratioCardHidden); 148bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 149bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 150b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki if (mActionBar != null) { 151b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki // Amount of available space that is not being hidden by the bottom pane 152b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki final int topPaneHeight = (int) (slideOffset * mShortcutCardsListView.getHeight()); 153b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki 154b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki final int availableActionBarHeight = 155b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki Math.min(mActionBar.getHeight(), topPaneHeight); 156b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki mActionBar.setHideOffset(mActionBar.getHeight() - availableActionBarHeight); 157b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki 158b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki if (!mActionBar.isShowing()) { 159b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki mActionBar.show(); 160b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki } 161b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki } 162b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki } 163b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki 164b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki @Override 165b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki public void onPanelOpened(View panel) { 166b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki if (DEBUG) { 167b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki Log.d(TAG, "onPanelOpened"); 168b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki } 169b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki mIsPanelOpen = true; 170b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki } 171b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki 172b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki @Override 173b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki public void onPanelClosed(View panel) { 174b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki if (DEBUG) { 175b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki Log.d(TAG, "onPanelClosed"); 176b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki } 177b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki mIsPanelOpen = false; 178b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki } 179b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki }; 180b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki 181b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki public class ViewPagerAdapter extends FragmentPagerAdapter { 182b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki public ViewPagerAdapter(FragmentManager fm) { 183b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki super(fm); 184b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki } 185b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki 186b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki @Override 187b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki public Fragment getItem(int position) { 188b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki switch (position) { 189b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki case TAB_INDEX_SPEED_DIAL: 190b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki mSpeedDialFragment = new SpeedDialFragment(); 191b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki return mSpeedDialFragment; 192b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki case TAB_INDEX_RECENTS: 193b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki mRecentsFragment = new CallLogFragment(CallLogQueryHandler.CALL_TYPE_ALL, 194b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki MAX_RECENTS_ENTRIES, System.currentTimeMillis() - OLDEST_RECENTS_DATE); 195b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki mRecentsFragment.setHasFooterView(true); 196b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki return mRecentsFragment; 197b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki case TAB_INDEX_ALL_CONTACTS: 198b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki mAllContactsFragment = new AllContactsFragment(); 199b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki return mAllContactsFragment; 200b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki } 201b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki throw new IllegalStateException("No fragment at position " + position); 202b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki } 203b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki 204b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki @Override 205b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki public int getCount() { 206b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki return TAB_INDEX_COUNT; 207b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki } 208b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki 209b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki @Override 210b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki public CharSequence getPageTitle(int position) { 211b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki return mTabTitles[position]; 212b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki } 213b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki } 214b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki 215b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki @Override 216b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki public void onCreate(Bundle savedInstanceState) { 217b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki super.onCreate(savedInstanceState); 218b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki 219b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki mCallLogQueryHandler = new CallLogQueryHandler(getActivity().getContentResolver(), 220b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki this, 1); 221b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki final String currentCountryIso = GeoUtil.getCurrentCountryIso(getActivity()); 222b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki mCallLogAdapter = ObjectFactory.newCallLogAdapter(getActivity(), this, 223b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki new ContactInfoHelper(getActivity(), currentCountryIso), null, false); 224b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki 2253a219cc3f5045bdebfcd975bf857c6ff26886a22Yorke Lee mMergedAdapter = new ShortcutCardsAdapter(getActivity(), this, mCallLogAdapter); 2263a219cc3f5045bdebfcd975bf857c6ff26886a22Yorke Lee } 2273a219cc3f5045bdebfcd975bf857c6ff26886a22Yorke Lee 2283a219cc3f5045bdebfcd975bf857c6ff26886a22Yorke Lee @Override 2293a219cc3f5045bdebfcd975bf857c6ff26886a22Yorke Lee public void onStart() { 2303a219cc3f5045bdebfcd975bf857c6ff26886a22Yorke Lee super.onStart(); 2313a219cc3f5045bdebfcd975bf857c6ff26886a22Yorke Lee getLoaderManager().initLoader(MISSED_CALL_LOADER, null, new MissedCallLogLoaderListener()); 2323a219cc3f5045bdebfcd975bf857c6ff26886a22Yorke Lee } 2333a219cc3f5045bdebfcd975bf857c6ff26886a22Yorke Lee 2343a219cc3f5045bdebfcd975bf857c6ff26886a22Yorke Lee @Override 235b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki public void onResume() { 236b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki super.onResume(); 2379701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki final SharedPreferences prefs = getActivity().getSharedPreferences( 2389701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki DialtactsActivity.SHARED_PREFS_NAME, Context.MODE_PRIVATE); 2399701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki mLastCallShortcutDate = prefs.getLong(KEY_LAST_DISMISSED_CALL_SHORTCUT_DATE, 0); 2409701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki mActionBar = getActivity().getActionBar(); 2419701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki fetchCalls(); 2429701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki mCallLogAdapter.setLoading(true); 2439701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki } 2449701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki 2459701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki @Override 2469701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki public void onPause() { 2479701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki // Wipe the cache to refresh the call shortcut item. This is not that expensive because 2489701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki // it only contains one item. 2499701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki mCallLogAdapter.invalidateCache(); 2509701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki super.onPause(); 2519701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki } 2529701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki 2539701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki @Override 2549701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki public View onCreateView(LayoutInflater inflater, ViewGroup container, 2559701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki Bundle savedInstanceState) { 2569701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki final View parentView = inflater.inflate(R.layout.lists_fragment, container, false); 257e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov mViewPager = (ViewPager) parentView.findViewById(R.id.lists_pager); 258e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov mViewPagerAdapter = new ViewPagerAdapter(getChildFragmentManager()); 259619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey mViewPager.setAdapter(mViewPagerAdapter); 260619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey mViewPager.setOffscreenPageLimit(2); 261619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey mViewPager.setOnPageChangeListener(this); 262619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 263619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey mTabTitles = new String[TAB_INDEX_COUNT]; 264619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey mTabTitles[TAB_INDEX_SPEED_DIAL] = getResources().getString(R.string.tab_speed_dial); 265b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki mTabTitles[TAB_INDEX_RECENTS] = getResources().getString(R.string.tab_recents); 266bee1a6b2e7cbea778195890e442c9e50f2a4e6d9Dmitri Plotnikov mTabTitles[TAB_INDEX_ALL_CONTACTS] = getResources().getString(R.string.tab_all_contacts); 267400e50c1efeb601f6162bd829fdf33e9dc5252f6Makoto Onuki 268400e50c1efeb601f6162bd829fdf33e9dc5252f6Makoto Onuki mViewPagerTabs = (ViewPagerTabs) parentView.findViewById(R.id.lists_pager_header); 269400e50c1efeb601f6162bd829fdf33e9dc5252f6Makoto Onuki mViewPagerTabs.setViewPager(mViewPager); 270400e50c1efeb601f6162bd829fdf33e9dc5252f6Makoto Onuki addOnPageChangeListener(mViewPagerTabs); 271619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 27224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro mShortcutCardsListView = (ListView) parentView.findViewById(R.id.shortcut_card_list); 273eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee mShortcutCardsListView.setAdapter(mMergedAdapter); 274e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov 275619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey mRemoveView = (RemoveView) parentView.findViewById(R.id.remove_view); 276212975b9dbb3c164e11732b98266eb7361e27ac5Makoto Onuki mRemoveViewContent = parentView.findViewById(R.id.remove_view_content); 277212975b9dbb3c164e11732b98266eb7361e27ac5Makoto Onuki 278212975b9dbb3c164e11732b98266eb7361e27ac5Makoto Onuki setupPaneLayout((OverlappingPaneLayout) parentView); 279212975b9dbb3c164e11732b98266eb7361e27ac5Makoto Onuki 280212975b9dbb3c164e11732b98266eb7361e27ac5Makoto Onuki return parentView; 281212975b9dbb3c164e11732b98266eb7361e27ac5Makoto Onuki } 282212975b9dbb3c164e11732b98266eb7361e27ac5Makoto Onuki 283212975b9dbb3c164e11732b98266eb7361e27ac5Makoto Onuki @Override 284bee1a6b2e7cbea778195890e442c9e50f2a4e6d9Dmitri Plotnikov public void onVoicemailStatusFetched(Cursor statusCursor) { 285bee1a6b2e7cbea778195890e442c9e50f2a4e6d9Dmitri Plotnikov // no-op 28635997f3fdee2984b6d5373326110eda26929001aMakoto Onuki } 28735997f3fdee2984b6d5373326110eda26929001aMakoto Onuki 28889b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov @Override 28989b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov public void onCallsFetched(Cursor cursor) { 290f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro mCallLogAdapter.setLoading(false); 291f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 292f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // Save the date of the most recent call log item 293f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (cursor != null && cursor.moveToFirst()) { 294f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro mCurrentCallShortcutDate = cursor.getLong(CallLogQuery.DATE); 295f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 29689b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov 29789b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov mCallLogAdapter.changeCursor(cursor); 29889b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov mMergedAdapter.notifyDataSetChanged(); 29989b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov } 300bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 301bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov @Override 302bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov public void fetchCalls() { 303b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki mCallLogQueryHandler.fetchCalls(CallLogQueryHandler.CALL_TYPE_ALL, mLastCallShortcutDate); 304b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki } 305b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki 306b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki public void dismissShortcut(View view) { 307b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki mLastCallShortcutDate = mCurrentCallShortcutDate; 308b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki final SharedPreferences prefs = view.getContext().getSharedPreferences( 30989b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov DialtactsActivity.SHARED_PREFS_NAME, Context.MODE_PRIVATE); 31035997f3fdee2984b6d5373326110eda26929001aMakoto Onuki prefs.edit().putLong(KEY_LAST_DISMISSED_CALL_SHORTCUT_DATE, mLastCallShortcutDate) 31135997f3fdee2984b6d5373326110eda26929001aMakoto Onuki .apply(); 31235997f3fdee2984b6d5373326110eda26929001aMakoto Onuki fetchCalls(); 31335997f3fdee2984b6d5373326110eda26929001aMakoto Onuki } 31435997f3fdee2984b6d5373326110eda26929001aMakoto Onuki 3159701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki public void addOnPageChangeListener(OnPageChangeListener onPageChangeListener) { 3169701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki if (!mOnPageChangeListeners.contains(onPageChangeListener)) { 3179701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki mOnPageChangeListeners.add(onPageChangeListener); 3189701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki } 3199701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki } 32089b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov 321bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov @Override 322bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { 323b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki final int count = mOnPageChangeListeners.size(); 324e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov for (int i = 0; i < count; i++) { 325e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov mOnPageChangeListeners.get(i).onPageScrolled(position, positionOffset, 326e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov positionOffsetPixels); 327b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki } 328b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki } 329b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki 330b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki @Override 3319701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki public void onPageSelected(int position) { 332e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov final int count = mOnPageChangeListeners.size(); 3339701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki for (int i = 0; i < count; i++) { 3349701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki mOnPageChangeListeners.get(i).onPageSelected(position); 3359701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki } 3369701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki } 3379701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki 3389701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki @Override 33972e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov public void onPageScrollStateChanged(int state) { 34071142b333418ac7d589bd7522dad77b967f0bbe1Makoto Onuki final int count = mOnPageChangeListeners.size(); 34171142b333418ac7d589bd7522dad77b967f0bbe1Makoto Onuki for (int i = 0; i < count; i++) { 34271142b333418ac7d589bd7522dad77b967f0bbe1Makoto Onuki mOnPageChangeListeners.get(i).onPageScrollStateChanged(state); 34371142b333418ac7d589bd7522dad77b967f0bbe1Makoto Onuki } 3449701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki } 345bee1a6b2e7cbea778195890e442c9e50f2a4e6d9Dmitri Plotnikov 346c19d5519535bc05225eac5f7dfb830fda48497deMakoto Onuki public void showRemoveView(boolean show) { 347c19d5519535bc05225eac5f7dfb830fda48497deMakoto Onuki mRemoveViewContent.setVisibility(show ? View.VISIBLE : View.GONE); 348c19d5519535bc05225eac5f7dfb830fda48497deMakoto Onuki mRemoveView.setAlpha(show ? 0 : 1); 349c19d5519535bc05225eac5f7dfb830fda48497deMakoto Onuki mRemoveView.animate().alpha(show ? 1 : 0).start(); 350c19d5519535bc05225eac5f7dfb830fda48497deMakoto Onuki 351c19d5519535bc05225eac5f7dfb830fda48497deMakoto Onuki if (mShortcutCardsListView.getCount() > 0) { 352e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov View v = mShortcutCardsListView.getChildAt(0); 353619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey v.animate().withLayer() 354619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey .alpha(show ? REMOVE_VIEW_SHOWN_ALPHA : REMOVE_VIEW_HIDDEN_ALPHA) 35571142b333418ac7d589bd7522dad77b967f0bbe1Makoto Onuki .start(); 35671142b333418ac7d589bd7522dad77b967f0bbe1Makoto Onuki } 35771142b333418ac7d589bd7522dad77b967f0bbe1Makoto Onuki } 35871142b333418ac7d589bd7522dad77b967f0bbe1Makoto Onuki 35971142b333418ac7d589bd7522dad77b967f0bbe1Makoto Onuki public boolean shouldShowActionBar() { 36071142b333418ac7d589bd7522dad77b967f0bbe1Makoto Onuki return mIsPanelOpen && mActionBar != null; 36171142b333418ac7d589bd7522dad77b967f0bbe1Makoto Onuki } 36271142b333418ac7d589bd7522dad77b967f0bbe1Makoto Onuki 36324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro public boolean isPaneOpen() { 36424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro return mIsPanelOpen; 36524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 36624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 36724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private void setupPaneLayout(OverlappingPaneLayout paneLayout) { 36824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro // TODO: Remove the notion of a capturable view. The entire view be slideable, once 36924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro // the framework better supports nested scrolling. 37024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro paneLayout.setCapturableView(mViewPagerTabs); 371eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee paneLayout.openPane(); 372eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee paneLayout.setPanelSlideListener(mPanelSlideListener); 373eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee paneLayout.setIntermediatePinnedOffset( 374eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee ((HostInterface) getActivity()).getActionBarHeight()); 375eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee 376eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee LayoutTransition transition = paneLayout.getLayoutTransition(); 377eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee // Turns on animations for all types of layout changes so that they occur for 378eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee // height changes. 379619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey transition.enableTransitionType(LayoutTransition.CHANGING); 380619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 381619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 382619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey public SpeedDialFragment getSpeedDialFragment() { 383619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey return mSpeedDialFragment; 384619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 385619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 386619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey public RemoveView getRemoveView() { 387619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey return mRemoveView; 388619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 389619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey} 390b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov