ListsFragment.java revision 4de59fb9ceac10ed429cd8416251329aa03ad266
1package com.android.dialer.list; 2 3import android.animation.LayoutTransition; 4import android.app.ActionBar; 5import android.app.Fragment; 6import android.app.FragmentManager; 7import android.content.Context; 8import android.content.SharedPreferences; 9import android.database.Cursor; 10import android.os.Bundle; 11import android.os.Trace; 12import android.preference.PreferenceManager; 13import android.provider.CallLog.Calls; 14import android.support.v13.app.FragmentPagerAdapter; 15import android.support.v4.view.ViewPager; 16import android.support.v4.view.ViewPager.OnPageChangeListener; 17import android.util.Log; 18import android.view.LayoutInflater; 19import android.view.View; 20import android.view.ViewGroup; 21import android.widget.AbsListView; 22import android.widget.ListView; 23 24import com.android.contacts.common.GeoUtil; 25import com.android.contacts.common.list.ViewPagerTabs; 26import com.android.contacts.commonbind.analytics.AnalyticsUtil; 27import com.android.dialer.DialtactsActivity; 28import com.android.dialer.R; 29import com.android.dialer.calllog.CallLogFragment; 30import com.android.dialer.calllog.CallLogQueryHandler; 31import com.android.dialer.calllog.ContactInfoHelper; 32import com.android.dialer.util.DialerUtils; 33import com.android.dialer.voicemail.VoicemailStatusHelper; 34import com.android.dialer.voicemail.VoicemailStatusHelperImpl; 35import com.android.dialer.widget.ActionBarController; 36import com.android.dialerbind.ObjectFactory; 37 38import java.util.ArrayList; 39 40/** 41 * Fragment that is used as the main screen of the Dialer. 42 * 43 * Contains a ViewPager that contains various contact lists like the Speed Dial list and the 44 * All Contacts list. This will also eventually contain the logic that allows sliding the 45 * ViewPager containing the lists up above the search bar and pin it against the top of the 46 * screen. 47 */ 48public class ListsFragment extends Fragment 49 implements ViewPager.OnPageChangeListener, CallLogQueryHandler.Listener { 50 51 private static final boolean DEBUG = DialtactsActivity.DEBUG; 52 private static final String TAG = "ListsFragment"; 53 54 public static final int TAB_INDEX_SPEED_DIAL = 0; 55 public static final int TAB_INDEX_HISTORY = 1; 56 public static final int TAB_INDEX_ALL_CONTACTS = 2; 57 public static final int TAB_INDEX_VOICEMAIL = 3; 58 59 public static final int TAB_COUNT_DEFAULT = 3; 60 public static final int TAB_COUNT_WITH_VOICEMAIL = 4; 61 62 private static final String PREF_KEY_HAS_ACTIVE_VOICEMAIL_PROVIDER = 63 "has_active_voicemail_provider"; 64 65 public interface HostInterface { 66 public ActionBarController getActionBarController(); 67 } 68 69 private ActionBar mActionBar; 70 private ViewPager mViewPager; 71 private ViewPagerTabs mViewPagerTabs; 72 private ViewPagerAdapter mViewPagerAdapter; 73 private RemoveView mRemoveView; 74 private View mRemoveViewContent; 75 76 private SpeedDialFragment mSpeedDialFragment; 77 private CallLogFragment mHistoryFragment; 78 private AllContactsFragment mAllContactsFragment; 79 private CallLogFragment mVoicemailFragment; 80 81 private SharedPreferences mPrefs; 82 private boolean mHasActiveVoicemailProvider; 83 private boolean mHasFetchedVoicemailStatus; 84 private boolean mShowVoicemailTabAfterVoicemailStatusIsFetched; 85 86 private VoicemailStatusHelper mVoicemailStatusHelper; 87 private ArrayList<OnPageChangeListener> mOnPageChangeListeners = 88 new ArrayList<OnPageChangeListener>(); 89 90 private String[] mTabTitles; 91 private int[] mTabIcons; 92 93 /** 94 * The position of the currently selected tab. 95 */ 96 private int mTabIndex = TAB_INDEX_SPEED_DIAL; 97 98 public class ViewPagerAdapter extends FragmentPagerAdapter { 99 public ViewPagerAdapter(FragmentManager fm) { 100 super(fm); 101 } 102 103 @Override 104 public long getItemId(int position) { 105 return getRtlPosition(position); 106 } 107 108 @Override 109 public Fragment getItem(int position) { 110 switch (getRtlPosition(position)) { 111 case TAB_INDEX_SPEED_DIAL: 112 mSpeedDialFragment = new SpeedDialFragment(); 113 return mSpeedDialFragment; 114 case TAB_INDEX_HISTORY: 115 mHistoryFragment = new CallLogFragment(CallLogQueryHandler.CALL_TYPE_ALL); 116 return mHistoryFragment; 117 case TAB_INDEX_ALL_CONTACTS: 118 mAllContactsFragment = new AllContactsFragment(); 119 return mAllContactsFragment; 120 case TAB_INDEX_VOICEMAIL: 121 mVoicemailFragment = new CallLogFragment(Calls.VOICEMAIL_TYPE); 122 return mVoicemailFragment; 123 } 124 throw new IllegalStateException("No fragment at position " + position); 125 } 126 127 @Override 128 public Object instantiateItem(ViewGroup container, int position) { 129 // On rotation the FragmentManager handles rotation. Therefore getItem() isn't called. 130 // Copy the fragments that the FragmentManager finds so that we can store them in 131 // instance variables for later. 132 final Fragment fragment = 133 (Fragment) super.instantiateItem(container, position); 134 if (fragment instanceof SpeedDialFragment) { 135 mSpeedDialFragment = (SpeedDialFragment) fragment; 136 } else if (fragment instanceof CallLogFragment && position == TAB_INDEX_HISTORY) { 137 mHistoryFragment = (CallLogFragment) fragment; 138 } else if (fragment instanceof AllContactsFragment) { 139 mAllContactsFragment = (AllContactsFragment) fragment; 140 } else if (fragment instanceof CallLogFragment && position == TAB_INDEX_VOICEMAIL) { 141 mVoicemailFragment = (CallLogFragment) fragment; 142 } 143 return fragment; 144 } 145 146 @Override 147 public int getCount() { 148 return mHasActiveVoicemailProvider ? TAB_COUNT_WITH_VOICEMAIL : TAB_COUNT_DEFAULT; 149 } 150 151 @Override 152 public CharSequence getPageTitle(int position) { 153 return mTabTitles[position]; 154 } 155 } 156 157 @Override 158 public void onCreate(Bundle savedInstanceState) { 159 Trace.beginSection(TAG + " onCreate"); 160 super.onCreate(savedInstanceState); 161 162 Trace.beginSection(TAG + " getCurrentCountryIso"); 163 final String currentCountryIso = GeoUtil.getCurrentCountryIso(getActivity()); 164 Trace.endSection(); 165 166 mVoicemailStatusHelper = new VoicemailStatusHelperImpl(); 167 mHasFetchedVoicemailStatus = false; 168 169 mPrefs = PreferenceManager.getDefaultSharedPreferences(getActivity()); 170 mHasActiveVoicemailProvider = mPrefs.getBoolean( 171 PREF_KEY_HAS_ACTIVE_VOICEMAIL_PROVIDER, false); 172 173 Trace.endSection(); 174 } 175 176 @Override 177 public void onResume() { 178 Trace.beginSection(TAG + " onResume"); 179 super.onResume(); 180 mActionBar = getActivity().getActionBar(); 181 if (getUserVisibleHint()) { 182 sendScreenViewForCurrentPosition(); 183 } 184 185 // Fetch voicemail status to determine if we should show the voicemail tab. 186 CallLogQueryHandler callLogQueryHandler = 187 new CallLogQueryHandler(getActivity(), getActivity().getContentResolver(), this); 188 callLogQueryHandler.fetchVoicemailStatus(); 189 Trace.endSection(); 190 } 191 192 @Override 193 public View onCreateView(LayoutInflater inflater, ViewGroup container, 194 Bundle savedInstanceState) { 195 Trace.beginSection(TAG + " onCreateView"); 196 Trace.beginSection(TAG + " inflate view"); 197 final View parentView = inflater.inflate(R.layout.lists_fragment, container, false); 198 Trace.endSection(); 199 Trace.beginSection(TAG + " setup views"); 200 mViewPager = (ViewPager) parentView.findViewById(R.id.lists_pager); 201 mViewPagerAdapter = new ViewPagerAdapter(getChildFragmentManager()); 202 mViewPager.setAdapter(mViewPagerAdapter); 203 mViewPager.setOffscreenPageLimit(TAB_COUNT_WITH_VOICEMAIL - 1); 204 mViewPager.setOnPageChangeListener(this); 205 showTab(TAB_INDEX_SPEED_DIAL); 206 207 mTabTitles = new String[TAB_COUNT_WITH_VOICEMAIL]; 208 mTabTitles[TAB_INDEX_SPEED_DIAL] = getResources().getString(R.string.tab_speed_dial); 209 mTabTitles[TAB_INDEX_HISTORY] = getResources().getString(R.string.tab_history); 210 mTabTitles[TAB_INDEX_ALL_CONTACTS] = getResources().getString(R.string.tab_all_contacts); 211 mTabTitles[TAB_INDEX_VOICEMAIL] = getResources().getString(R.string.tab_voicemail); 212 213 mTabIcons = new int[TAB_COUNT_WITH_VOICEMAIL]; 214 mTabIcons[TAB_INDEX_SPEED_DIAL] = R.drawable.tab_speed_dial; 215 mTabIcons[TAB_INDEX_HISTORY] = R.drawable.tab_history; 216 mTabIcons[TAB_INDEX_ALL_CONTACTS] = R.drawable.tab_contacts; 217 mTabIcons[TAB_INDEX_VOICEMAIL] = R.drawable.tab_voicemail; 218 219 mViewPagerTabs = (ViewPagerTabs) parentView.findViewById(R.id.lists_pager_header); 220 mViewPagerTabs.setTabIcons(mTabIcons); 221 mViewPagerTabs.setViewPager(mViewPager); 222 addOnPageChangeListener(mViewPagerTabs); 223 224 mRemoveView = (RemoveView) parentView.findViewById(R.id.remove_view); 225 mRemoveViewContent = parentView.findViewById(R.id.remove_view_content); 226 227 Trace.endSection(); 228 Trace.endSection(); 229 return parentView; 230 } 231 232 public void addOnPageChangeListener(OnPageChangeListener onPageChangeListener) { 233 if (!mOnPageChangeListeners.contains(onPageChangeListener)) { 234 mOnPageChangeListeners.add(onPageChangeListener); 235 } 236 } 237 238 /** 239 * Shows the tab with the specified index. If the voicemail tab index is specified, but the 240 * voicemail status hasn't been fetched, it will try to show the tab after the voicemail status 241 * has been fetched. 242 */ 243 public void showTab(int index) { 244 if (index == TAB_INDEX_VOICEMAIL) { 245 if (mHasActiveVoicemailProvider) { 246 mViewPager.setCurrentItem(getRtlPosition(TAB_INDEX_VOICEMAIL)); 247 } else if (!mHasFetchedVoicemailStatus) { 248 // Try to show the voicemail tab after the voicemail status returns. 249 mShowVoicemailTabAfterVoicemailStatusIsFetched = true; 250 } 251 } else { 252 mViewPager.setCurrentItem(getRtlPosition(index)); 253 } 254 } 255 256 @Override 257 public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { 258 mTabIndex = getRtlPosition(position); 259 260 final int count = mOnPageChangeListeners.size(); 261 for (int i = 0; i < count; i++) { 262 mOnPageChangeListeners.get(i).onPageScrolled(position, positionOffset, 263 positionOffsetPixels); 264 } 265 } 266 267 @Override 268 public void onPageSelected(int position) { 269 mTabIndex = getRtlPosition(position); 270 271 // Show the tab which has been selected instead. 272 mShowVoicemailTabAfterVoicemailStatusIsFetched = false; 273 274 final int count = mOnPageChangeListeners.size(); 275 for (int i = 0; i < count; i++) { 276 mOnPageChangeListeners.get(i).onPageSelected(position); 277 } 278 sendScreenViewForCurrentPosition(); 279 } 280 281 @Override 282 public void onPageScrollStateChanged(int state) { 283 final int count = mOnPageChangeListeners.size(); 284 for (int i = 0; i < count; i++) { 285 mOnPageChangeListeners.get(i).onPageScrollStateChanged(state); 286 } 287 } 288 289 @Override 290 public void onVoicemailStatusFetched(Cursor statusCursor) { 291 mHasFetchedVoicemailStatus = true; 292 293 if (getActivity() == null || getActivity().isFinishing()) { 294 return; 295 } 296 297 // Update mHasActiveVoicemailProvider, which controls the number of tabs displayed. 298 boolean hasActiveVoicemailProvider = 299 mVoicemailStatusHelper.getNumberActivityVoicemailSources(statusCursor) > 0; 300 if (hasActiveVoicemailProvider != mHasActiveVoicemailProvider) { 301 mHasActiveVoicemailProvider = hasActiveVoicemailProvider; 302 mViewPagerAdapter.notifyDataSetChanged(); 303 mViewPagerTabs.setViewPager(mViewPager); 304 305 mPrefs.edit() 306 .putBoolean(PREF_KEY_HAS_ACTIVE_VOICEMAIL_PROVIDER, hasActiveVoicemailProvider) 307 .commit(); 308 } 309 310 if (mHasActiveVoicemailProvider && mShowVoicemailTabAfterVoicemailStatusIsFetched) { 311 mShowVoicemailTabAfterVoicemailStatusIsFetched = false; 312 showTab(TAB_INDEX_VOICEMAIL); 313 } 314 } 315 316 @Override 317 public boolean onCallsFetched(Cursor statusCursor) { 318 // Return false; did not take ownership of cursor 319 return false; 320 } 321 322 public int getCurrentTabIndex() { 323 return mTabIndex; 324 } 325 326 public void showRemoveView(boolean show) { 327 mRemoveViewContent.setVisibility(show ? View.VISIBLE : View.GONE); 328 mRemoveView.setAlpha(show ? 0 : 1); 329 mRemoveView.animate().alpha(show ? 1 : 0).start(); 330 } 331 332 public boolean shouldShowActionBar() { 333 // TODO: Update this based on scroll state. 334 return mActionBar != null; 335 } 336 337 public SpeedDialFragment getSpeedDialFragment() { 338 return mSpeedDialFragment; 339 } 340 341 public RemoveView getRemoveView() { 342 return mRemoveView; 343 } 344 345 public int getTabCount() { 346 return mViewPagerAdapter.getCount(); 347 } 348 349 private int getRtlPosition(int position) { 350 if (DialerUtils.isRtl()) { 351 return mViewPagerAdapter.getCount() - 1 - position; 352 } 353 return position; 354 } 355 356 public void sendScreenViewForCurrentPosition() { 357 if (!isResumed()) { 358 return; 359 } 360 361 String fragmentName; 362 switch (getCurrentTabIndex()) { 363 case TAB_INDEX_SPEED_DIAL: 364 fragmentName = SpeedDialFragment.class.getSimpleName(); 365 break; 366 case TAB_INDEX_HISTORY: 367 fragmentName = CallLogFragment.class.getSimpleName() + "#History"; 368 break; 369 case TAB_INDEX_ALL_CONTACTS: 370 fragmentName = AllContactsFragment.class.getSimpleName(); 371 break; 372 case TAB_INDEX_VOICEMAIL: 373 fragmentName = CallLogFragment.class.getSimpleName() + "#Voicemail"; 374 default: 375 return; 376 } 377 AnalyticsUtil.sendScreenView(fragmentName, getActivity(), null); 378 } 379} 380