ListsFragment.java revision 6a1461a86ad861b0e04333452e47cb81675459d5
1package com.android.dialer.list; 2 3import android.animation.LayoutTransition; 4import android.app.Fragment; 5import android.app.FragmentManager; 6import android.app.LoaderManager; 7import android.content.Context; 8import android.content.CursorLoader; 9import android.content.Loader; 10import android.content.SharedPreferences; 11import android.database.Cursor; 12import android.net.Uri; 13import android.os.Bundle; 14import android.provider.CallLog; 15import android.support.v13.app.FragmentPagerAdapter; 16import android.support.v4.view.ViewPager; 17import android.view.LayoutInflater; 18import android.view.View; 19import android.view.ViewGroup; 20import android.widget.LinearLayout; 21import android.widget.ListView; 22 23import com.android.contacts.common.GeoUtil; 24import com.android.dialer.DialtactsActivity; 25import android.view.View.OnClickListener; 26 27import com.android.dialer.R; 28import com.android.dialer.calllog.CallLogAdapter; 29import com.android.dialer.calllog.CallLogFragment; 30import com.android.dialer.calllog.CallLogQuery; 31import com.android.dialer.calllog.CallLogQueryHandler; 32import com.android.dialer.calllog.ContactInfoHelper; 33import com.android.dialerbind.ObjectFactory; 34 35/** 36 * Fragment that is used as the main screen of the Dialer. 37 * 38 * Contains a ViewPager that contains various contact lists like the Speed Dial list and the 39 * All Contacts list. This will also eventually contain the logic that allows sliding the 40 * ViewPager containing the lists up above the shortcut cards and pin it against the top of the 41 * screen. 42 */ 43public class ListsFragment extends Fragment implements CallLogQueryHandler.Listener, 44 CallLogAdapter.CallFetcher { 45 46 private static final int TAB_INDEX_SPEED_DIAL = 0; 47 private static final int TAB_INDEX_RECENTS = 1; 48 private static final int TAB_INDEX_ALL_CONTACTS = 2; 49 50 private static final int TAB_INDEX_COUNT = 3; 51 52 private static final int MAX_RECENTS_ENTRIES = 20; 53 // Oldest recents entry to display is 2 weeks old. 54 private static final long OLDEST_RECENTS_DATE = 1000L * 60 * 60 * 24 * 14; 55 56 private static final String KEY_LAST_DISMISSED_CALL_SHORTCUT_DATE = 57 "key_last_dismissed_call_shortcut_date"; 58 59 // Used with LoaderManager 60 private static int MISSED_CALL_LOADER = 1; 61 62 public interface HostInterface { 63 public void showCallHistory(); 64 } 65 66 private ViewPager mViewPager; 67 private ViewPagerAdapter mViewPagerAdapter; 68 private PhoneFavoriteFragment mSpeedDialFragment; 69 private CallLogFragment mRecentsFragment; 70 private AllContactsFragment mAllContactsFragment; 71 72 private String[] mTabTitles; 73 74 private PhoneFavoriteMergedAdapter mMergedAdapter; 75 private CallLogAdapter mCallLogAdapter; 76 private CallLogQueryHandler mCallLogQueryHandler; 77 78 /** 79 * Call shortcuts older than this date (persisted in shared preferences) will not show up in 80 * at the top of the screen 81 */ 82 private long mLastCallShortcutDate = 0; 83 84 /** 85 * The date of the current call shortcut that is showing on screen. 86 */ 87 private long mCurrentCallShortcutDate = 0; 88 89 private class MissedCallLogLoaderListener implements LoaderManager.LoaderCallbacks<Cursor> { 90 91 @Override 92 public Loader<Cursor> onCreateLoader(int id, Bundle args) { 93 final Uri uri = CallLog.Calls.CONTENT_URI; 94 final String[] projection = new String[] {CallLog.Calls.TYPE}; 95 final String selection = CallLog.Calls.TYPE + " = " + CallLog.Calls.MISSED_TYPE + 96 " AND " + CallLog.Calls.IS_READ + " = 0"; 97 return new CursorLoader(getActivity(), uri, projection, selection, null, null); 98 } 99 100 @Override 101 public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor data) { 102 mCallLogAdapter.setMissedCalls(data); 103 } 104 105 @Override 106 public void onLoaderReset(Loader<Cursor> cursorLoader) { 107 } 108 } 109 110 public class ViewPagerAdapter extends FragmentPagerAdapter { 111 public ViewPagerAdapter(FragmentManager fm) { 112 super(fm); 113 } 114 115 @Override 116 public Fragment getItem(int position) { 117 switch (position) { 118 case TAB_INDEX_SPEED_DIAL: 119 mSpeedDialFragment = new PhoneFavoriteFragment(); 120 return mSpeedDialFragment; 121 case TAB_INDEX_RECENTS: 122 mRecentsFragment = new CallLogFragment(CallLogQueryHandler.CALL_TYPE_ALL, 123 MAX_RECENTS_ENTRIES, System.currentTimeMillis() - OLDEST_RECENTS_DATE); 124 125 /* 126 * Provide mViewPager as a parent viewgroup for the inflation of the footer, 127 * to ensure that the footer view is inflated with the correct LayoutParams. 128 * If root is null in 129 * inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot), 130 * the layout parameters specified in R.layout.recents_list_footer are not 131 * correctly applied. The footer view is ultimately not attached to mViewPager. 132 */ 133 final View viewFullHistoryFooter = getActivity().getLayoutInflater().inflate( 134 R.layout.recents_list_footer, mViewPager, false); 135 viewFullHistoryFooter.setOnClickListener(new OnClickListener() { 136 @Override 137 public void onClick(View v) { 138 ((HostInterface) getActivity()).showCallHistory(); 139 } 140 }); 141 mRecentsFragment.setFooterView(viewFullHistoryFooter); 142 return mRecentsFragment; 143 case TAB_INDEX_ALL_CONTACTS: 144 mAllContactsFragment = new AllContactsFragment(); 145 return mAllContactsFragment; 146 } 147 throw new IllegalStateException("No fragment at position " + position); 148 } 149 150 @Override 151 public int getCount() { 152 return TAB_INDEX_COUNT; 153 } 154 155 @Override 156 public CharSequence getPageTitle(int position) { 157 return mTabTitles[position]; 158 } 159 } 160 161 @Override 162 public void onCreate(Bundle savedInstanceState) { 163 super.onCreate(savedInstanceState); 164 165 mCallLogQueryHandler = new CallLogQueryHandler(getActivity().getContentResolver(), 166 this, 1); 167 final String currentCountryIso = GeoUtil.getCurrentCountryIso(getActivity()); 168 mCallLogAdapter = ObjectFactory.newCallLogAdapter(getActivity(), this, 169 new ContactInfoHelper(getActivity(), currentCountryIso), false, false); 170 171 mMergedAdapter = new PhoneFavoriteMergedAdapter(getActivity(), this, null, 172 mCallLogAdapter, null, null); 173 } 174 175 @Override 176 public void onStart() { 177 super.onStart(); 178 getLoaderManager().initLoader(MISSED_CALL_LOADER, null, new MissedCallLogLoaderListener()); 179 } 180 181 @Override 182 public void onResume() { 183 super.onResume(); 184 final SharedPreferences prefs = getActivity().getSharedPreferences( 185 DialtactsActivity.SHARED_PREFS_NAME, Context.MODE_PRIVATE); 186 mLastCallShortcutDate = prefs.getLong(KEY_LAST_DISMISSED_CALL_SHORTCUT_DATE, 0); 187 188 fetchCalls(); 189 mCallLogAdapter.setLoading(true); 190 } 191 192 @Override 193 public void onPause() { 194 // Wipe the cache to refresh the call shortcut item. This is not that expensive because 195 // it only contains one item. 196 mCallLogAdapter.invalidateCache(); 197 super.onPause(); 198 } 199 200 @Override 201 public View onCreateView(LayoutInflater inflater, ViewGroup container, 202 Bundle savedInstanceState) { 203 final View parentView = inflater.inflate(R.layout.lists_fragment, container, false); 204 mViewPager = (ViewPager) parentView.findViewById(R.id.lists_pager); 205 mViewPagerAdapter = new ViewPagerAdapter(getChildFragmentManager()); 206 mViewPager.setAdapter(mViewPagerAdapter); 207 mViewPager.setOffscreenPageLimit(2); 208 209 mTabTitles = new String[TAB_INDEX_COUNT]; 210 mTabTitles[TAB_INDEX_SPEED_DIAL] = getResources().getString(R.string.tab_speed_dial); 211 mTabTitles[TAB_INDEX_RECENTS] = getResources().getString(R.string.tab_recents); 212 mTabTitles[TAB_INDEX_ALL_CONTACTS] = getResources().getString(R.string.tab_all_contacts); 213 214 ViewPagerTabs tabs = (ViewPagerTabs) parentView.findViewById(R.id.lists_pager_header); 215 tabs.setViewPager(mViewPager); 216 217 final ListView shortcutCardsListView = 218 (ListView) parentView.findViewById(R.id.shortcut_card_list); 219 shortcutCardsListView.setAdapter(mMergedAdapter); 220 221 LayoutTransition transition = ((LinearLayout) parentView).getLayoutTransition(); 222 // Turns on animations for all types of layout changes so that they occur for 223 // height changes. 224 transition.enableTransitionType(LayoutTransition.CHANGING); 225 return parentView; 226 } 227 228 @Override 229 public void onVoicemailStatusFetched(Cursor statusCursor) { 230 // no-op 231 } 232 233 @Override 234 public void onCallsFetched(Cursor cursor) { 235 mCallLogAdapter.setLoading(false); 236 237 // Save the date of the most recent call log item 238 if (cursor != null && cursor.moveToFirst()) { 239 mCurrentCallShortcutDate = cursor.getLong(CallLogQuery.DATE); 240 } 241 242 mCallLogAdapter.changeCursor(cursor); 243 mMergedAdapter.notifyDataSetChanged(); 244 } 245 246 @Override 247 public void fetchCalls() { 248 mCallLogQueryHandler.fetchCalls(CallLogQueryHandler.CALL_TYPE_ALL, mLastCallShortcutDate); 249 } 250 251 public void dismissShortcut(View view) { 252 mLastCallShortcutDate = mCurrentCallShortcutDate; 253 final SharedPreferences prefs = view.getContext().getSharedPreferences( 254 DialtactsActivity.SHARED_PREFS_NAME, Context.MODE_PRIVATE); 255 prefs.edit().putLong(KEY_LAST_DISMISSED_CALL_SHORTCUT_DATE, mLastCallShortcutDate) 256 .apply(); 257 fetchCalls(); 258 } 259} 260