Java tutorial
/* * Copyright (C) 2013 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.dialer.list; import android.app.Fragment; import android.app.FragmentManager; import android.content.SharedPreferences; import android.database.Cursor; import android.os.Bundle; import android.os.Trace; import android.preference.PreferenceManager; import android.provider.CallLog.Calls; import android.support.v13.app.FragmentPagerAdapter; import android.support.v4.view.ViewPager; import android.support.v4.view.ViewPager.OnPageChangeListener; import android.support.v7.app.ActionBar; import android.support.v7.app.AppCompatActivity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import com.android.contacts.common.list.ViewPagerTabs; import com.android.dialer.DialtactsActivity; import com.android.dialer.R; import com.android.dialer.calllog.CallLogFragment; import com.android.dialer.calllog.CallLogNotificationsHelper; import com.android.dialer.calllog.CallLogQueryHandler; import com.android.dialer.calllog.VisualVoicemailCallLogFragment; import com.android.dialer.logging.Logger; import com.android.dialer.logging.ScreenEvent; import com.android.dialer.util.DialerUtils; import com.android.dialer.voicemail.VisualVoicemailEnabledChecker; import com.android.dialer.voicemail.VoicemailStatusHelper; import com.android.dialer.voicemail.VoicemailStatusHelperImpl; import com.android.dialer.widget.ActionBarController; import java.util.ArrayList; import java.util.List; /** * Fragment that is used as the main screen of the Dialer. * * Contains a ViewPager that contains various contact lists like the Speed Dial list and the * All Contacts list. This will also eventually contain the logic that allows sliding the * ViewPager containing the lists up above the search bar and pin it against the top of the * screen. */ public class ListsFragment extends Fragment implements ViewPager.OnPageChangeListener, CallLogQueryHandler.Listener { private static final boolean DEBUG = DialtactsActivity.DEBUG; private static final String TAG = "ListsFragment"; public static final int TAB_INDEX_SPEED_DIAL = 0; public static final int TAB_INDEX_HISTORY = 1; public static final int TAB_INDEX_ALL_CONTACTS = 2; public static final int TAB_INDEX_VOICEMAIL = 3; public static final int TAB_COUNT_DEFAULT = 3; public static final int TAB_COUNT_WITH_VOICEMAIL = 4; public interface HostInterface { public ActionBarController getActionBarController(); } private ActionBar mActionBar; private ViewPager mViewPager; private ViewPagerTabs mViewPagerTabs; private ViewPagerAdapter mViewPagerAdapter; private RemoveView mRemoveView; private View mRemoveViewContent; private SpeedDialFragment mSpeedDialFragment; private CallLogFragment mHistoryFragment; private AllContactsFragment mAllContactsFragment; private CallLogFragment mVoicemailFragment; private SharedPreferences mPrefs; private boolean mHasActiveVoicemailProvider; private boolean mHasFetchedVoicemailStatus; private boolean mShowVoicemailTabAfterVoicemailStatusIsFetched; private VoicemailStatusHelper mVoicemailStatusHelper; private ArrayList<OnPageChangeListener> mOnPageChangeListeners = new ArrayList<OnPageChangeListener>(); private String[] mTabTitles; private int[] mTabIcons; /** * The position of the currently selected tab. */ private int mTabIndex = TAB_INDEX_SPEED_DIAL; private CallLogQueryHandler mCallLogQueryHandler; public class ViewPagerAdapter extends FragmentPagerAdapter { private final List<Fragment> mFragments = new ArrayList<>(); public ViewPagerAdapter(FragmentManager fm) { super(fm); for (int i = 0; i < TAB_COUNT_WITH_VOICEMAIL; i++) { mFragments.add(null); } } @Override public long getItemId(int position) { return getRtlPosition(position); } @Override public Fragment getItem(int position) { switch (getRtlPosition(position)) { case TAB_INDEX_SPEED_DIAL: mSpeedDialFragment = new SpeedDialFragment(); return mSpeedDialFragment; case TAB_INDEX_HISTORY: mHistoryFragment = new CallLogFragment(CallLogQueryHandler.CALL_TYPE_ALL); return mHistoryFragment; case TAB_INDEX_ALL_CONTACTS: mAllContactsFragment = new AllContactsFragment(); return mAllContactsFragment; case TAB_INDEX_VOICEMAIL: mVoicemailFragment = new VisualVoicemailCallLogFragment(); return mVoicemailFragment; } throw new IllegalStateException("No fragment at position " + position); } @Override public Fragment instantiateItem(ViewGroup container, int position) { // On rotation the FragmentManager handles rotation. Therefore getItem() isn't called. // Copy the fragments that the FragmentManager finds so that we can store them in // instance variables for later. final Fragment fragment = (Fragment) super.instantiateItem(container, position); if (fragment instanceof SpeedDialFragment) { mSpeedDialFragment = (SpeedDialFragment) fragment; } else if (fragment instanceof CallLogFragment && position == TAB_INDEX_HISTORY) { mHistoryFragment = (CallLogFragment) fragment; } else if (fragment instanceof AllContactsFragment) { mAllContactsFragment = (AllContactsFragment) fragment; } else if (fragment instanceof CallLogFragment && position == TAB_INDEX_VOICEMAIL) { mVoicemailFragment = (CallLogFragment) fragment; } mFragments.set(position, fragment); return fragment; } /** * When {@link android.support.v4.view.PagerAdapter#notifyDataSetChanged} is called, * this method is called on all pages to determine whether they need to be recreated. * When the voicemail tab is removed, the view needs to be recreated by returning * POSITION_NONE. If notifyDataSetChanged is called for some other reason, the voicemail * tab is recreated only if it is active. All other tabs do not need to be recreated * and POSITION_UNCHANGED is returned. */ @Override public int getItemPosition(Object object) { return !mHasActiveVoicemailProvider && mFragments.indexOf(object) == TAB_INDEX_VOICEMAIL ? POSITION_NONE : POSITION_UNCHANGED; } @Override public int getCount() { return mHasActiveVoicemailProvider ? TAB_COUNT_WITH_VOICEMAIL : TAB_COUNT_DEFAULT; } @Override public CharSequence getPageTitle(int position) { return mTabTitles[position]; } } @Override public void onCreate(Bundle savedInstanceState) { Trace.beginSection(TAG + " onCreate"); super.onCreate(savedInstanceState); mVoicemailStatusHelper = new VoicemailStatusHelperImpl(); mHasFetchedVoicemailStatus = false; mPrefs = PreferenceManager.getDefaultSharedPreferences(getActivity()); mHasActiveVoicemailProvider = mPrefs .getBoolean(VisualVoicemailEnabledChecker.PREF_KEY_HAS_ACTIVE_VOICEMAIL_PROVIDER, false); Trace.endSection(); } @Override public void onResume() { Trace.beginSection(TAG + " onResume"); super.onResume(); mActionBar = ((AppCompatActivity) getActivity()).getSupportActionBar(); if (getUserVisibleHint()) { sendScreenViewForCurrentPosition(); } // Fetch voicemail status to determine if we should show the voicemail tab. mCallLogQueryHandler = new CallLogQueryHandler(getActivity(), getActivity().getContentResolver(), this); mCallLogQueryHandler.fetchVoicemailStatus(); mCallLogQueryHandler.fetchMissedCallsUnreadCount(); Trace.endSection(); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { Trace.beginSection(TAG + " onCreateView"); Trace.beginSection(TAG + " inflate view"); final View parentView = inflater.inflate(R.layout.lists_fragment, container, false); Trace.endSection(); Trace.beginSection(TAG + " setup views"); mViewPager = (ViewPager) parentView.findViewById(R.id.lists_pager); mViewPagerAdapter = new ViewPagerAdapter(getChildFragmentManager()); mViewPager.setAdapter(mViewPagerAdapter); mViewPager.setOffscreenPageLimit(TAB_COUNT_WITH_VOICEMAIL - 1); mViewPager.setOnPageChangeListener(this); showTab(TAB_INDEX_SPEED_DIAL); mTabTitles = new String[TAB_COUNT_WITH_VOICEMAIL]; mTabTitles[TAB_INDEX_SPEED_DIAL] = getResources().getString(R.string.tab_speed_dial); mTabTitles[TAB_INDEX_HISTORY] = getResources().getString(R.string.tab_history); mTabTitles[TAB_INDEX_ALL_CONTACTS] = getResources().getString(R.string.tab_all_contacts); mTabTitles[TAB_INDEX_VOICEMAIL] = getResources().getString(R.string.tab_voicemail); mTabIcons = new int[TAB_COUNT_WITH_VOICEMAIL]; mTabIcons[TAB_INDEX_SPEED_DIAL] = R.drawable.ic_grade_24dp; mTabIcons[TAB_INDEX_HISTORY] = R.drawable.ic_schedule_24dp; mTabIcons[TAB_INDEX_ALL_CONTACTS] = R.drawable.ic_people_24dp; mTabIcons[TAB_INDEX_VOICEMAIL] = R.drawable.ic_voicemail_24dp; mViewPagerTabs = (ViewPagerTabs) parentView.findViewById(R.id.lists_pager_header); mViewPagerTabs.configureTabIcons(mTabIcons); mViewPagerTabs.setViewPager(mViewPager); addOnPageChangeListener(mViewPagerTabs); mRemoveView = (RemoveView) parentView.findViewById(R.id.remove_view); mRemoveViewContent = parentView.findViewById(R.id.remove_view_content); Trace.endSection(); Trace.endSection(); return parentView; } public void addOnPageChangeListener(OnPageChangeListener onPageChangeListener) { if (!mOnPageChangeListeners.contains(onPageChangeListener)) { mOnPageChangeListeners.add(onPageChangeListener); } } /** * Shows the tab with the specified index. If the voicemail tab index is specified, but the * voicemail status hasn't been fetched, it will try to show the tab after the voicemail status * has been fetched. */ public void showTab(int index) { if (index == TAB_INDEX_VOICEMAIL) { if (mHasActiveVoicemailProvider) { mViewPager.setCurrentItem(getRtlPosition(TAB_INDEX_VOICEMAIL)); } else if (!mHasFetchedVoicemailStatus) { // Try to show the voicemail tab after the voicemail status returns. mShowVoicemailTabAfterVoicemailStatusIsFetched = true; } } else if (index < getTabCount()) { mViewPager.setCurrentItem(getRtlPosition(index)); } } @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { mTabIndex = getRtlPosition(position); final int count = mOnPageChangeListeners.size(); for (int i = 0; i < count; i++) { mOnPageChangeListeners.get(i).onPageScrolled(position, positionOffset, positionOffsetPixels); } } @Override public void onPageSelected(int position) { mTabIndex = getRtlPosition(position); // Show the tab which has been selected instead. mShowVoicemailTabAfterVoicemailStatusIsFetched = false; final int count = mOnPageChangeListeners.size(); for (int i = 0; i < count; i++) { mOnPageChangeListeners.get(i).onPageSelected(position); } sendScreenViewForCurrentPosition(); } @Override public void onPageScrollStateChanged(int state) { final int count = mOnPageChangeListeners.size(); for (int i = 0; i < count; i++) { mOnPageChangeListeners.get(i).onPageScrollStateChanged(state); } } @Override public void onVoicemailStatusFetched(Cursor statusCursor) { mHasFetchedVoicemailStatus = true; if (getActivity() == null || getActivity().isFinishing()) { return; } // Update mHasActiveVoicemailProvider, which controls the number of tabs displayed. boolean hasActiveVoicemailProvider = mVoicemailStatusHelper .getNumberActivityVoicemailSources(statusCursor) > 0; if (hasActiveVoicemailProvider != mHasActiveVoicemailProvider) { mHasActiveVoicemailProvider = hasActiveVoicemailProvider; mViewPagerAdapter.notifyDataSetChanged(); if (hasActiveVoicemailProvider) { mViewPagerTabs.updateTab(TAB_INDEX_VOICEMAIL); } else { mViewPagerTabs.removeTab(TAB_INDEX_VOICEMAIL); removeVoicemailFragment(); } mPrefs.edit().putBoolean(VisualVoicemailEnabledChecker.PREF_KEY_HAS_ACTIVE_VOICEMAIL_PROVIDER, hasActiveVoicemailProvider).commit(); } if (hasActiveVoicemailProvider) { mCallLogQueryHandler.fetchVoicemailUnreadCount(); } if (mHasActiveVoicemailProvider && mShowVoicemailTabAfterVoicemailStatusIsFetched) { mShowVoicemailTabAfterVoicemailStatusIsFetched = false; showTab(TAB_INDEX_VOICEMAIL); } } @Override public void onVoicemailUnreadCountFetched(Cursor cursor) { if (getActivity() == null || getActivity().isFinishing() || cursor == null) { return; } int count = 0; try { count = cursor.getCount(); } finally { cursor.close(); } mViewPagerTabs.setUnreadCount(count, TAB_INDEX_VOICEMAIL); mViewPagerTabs.updateTab(TAB_INDEX_VOICEMAIL); } @Override public void onMissedCallsUnreadCountFetched(Cursor cursor) { if (getActivity() == null || getActivity().isFinishing() || cursor == null) { return; } int count = 0; try { count = cursor.getCount(); } finally { cursor.close(); } mViewPagerTabs.setUnreadCount(count, TAB_INDEX_HISTORY); mViewPagerTabs.updateTab(TAB_INDEX_HISTORY); } @Override public boolean onCallsFetched(Cursor statusCursor) { // Return false; did not take ownership of cursor return false; } public int getCurrentTabIndex() { return mTabIndex; } /** * External method to update unread count because the unread count changes when the user * expands a voicemail in the call log or when the user expands an unread call in the call * history tab. */ public void updateTabUnreadCounts() { if (mCallLogQueryHandler != null) { mCallLogQueryHandler.fetchMissedCallsUnreadCount(); if (mHasActiveVoicemailProvider) { mCallLogQueryHandler.fetchVoicemailUnreadCount(); } } } /** * External method to mark all missed calls as read. */ public void markMissedCallsAsReadAndRemoveNotifications() { if (mCallLogQueryHandler != null) { mCallLogQueryHandler.markMissedCallsAsRead(); CallLogNotificationsHelper.removeMissedCallNotifications(getActivity()); } } public void showRemoveView(boolean show) { mRemoveViewContent.setVisibility(show ? View.VISIBLE : View.GONE); mRemoveView.setAlpha(show ? 0 : 1); mRemoveView.animate().alpha(show ? 1 : 0).start(); } public boolean shouldShowActionBar() { // TODO: Update this based on scroll state. return mActionBar != null; } public SpeedDialFragment getSpeedDialFragment() { return mSpeedDialFragment; } public RemoveView getRemoveView() { return mRemoveView; } public int getTabCount() { return mViewPagerAdapter.getCount(); } private int getRtlPosition(int position) { if (DialerUtils.isRtl()) { return mViewPagerAdapter.getCount() - 1 - position; } return position; } public void sendScreenViewForCurrentPosition() { if (!isResumed()) { return; } int screenType; switch (getCurrentTabIndex()) { case TAB_INDEX_SPEED_DIAL: screenType = ScreenEvent.SPEED_DIAL; break; case TAB_INDEX_HISTORY: screenType = ScreenEvent.CALL_LOG; break; case TAB_INDEX_ALL_CONTACTS: screenType = ScreenEvent.ALL_CONTACTS; break; case TAB_INDEX_VOICEMAIL: screenType = ScreenEvent.VOICEMAIL_LOG; default: return; } Logger.logScreenView(screenType, getActivity()); } private void removeVoicemailFragment() { if (mVoicemailFragment != null) { getChildFragmentManager().beginTransaction().remove(mVoicemailFragment).commitAllowingStateLoss(); mVoicemailFragment = null; } } }