1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.dialer.app.list; 18 19 import android.app.Fragment; 20 import android.app.FragmentManager; 21 import android.content.Context; 22 import android.support.annotation.IntDef; 23 import android.support.v13.app.FragmentPagerAdapter; 24 import android.view.ViewGroup; 25 import com.android.dialer.app.calllog.CallLogFragment; 26 import com.android.dialer.app.calllog.VisualVoicemailCallLogFragment; 27 import com.android.dialer.calllog.CallLogComponent; 28 import com.android.dialer.calllog.CallLogFramework; 29 import com.android.dialer.calllog.ui.NewCallLogFragment; 30 import com.android.dialer.common.Assert; 31 import com.android.dialer.common.ConfigProviderBindings; 32 import com.android.dialer.common.LogUtil; 33 import com.android.dialer.contactsfragment.ContactsFragment; 34 import com.android.dialer.database.CallLogQueryHandler; 35 import com.android.dialer.speeddial.SpeedDialFragment; 36 import com.android.dialer.util.ViewUtil; 37 import java.lang.annotation.Retention; 38 import java.lang.annotation.RetentionPolicy; 39 import java.util.ArrayList; 40 import java.util.Collections; 41 import java.util.List; 42 43 /** ViewPager adapter for {@link com.android.dialer.app.DialtactsActivity}. */ 44 public class DialtactsPagerAdapter extends FragmentPagerAdapter { 45 46 /** IntDef for indices of ViewPager tabs. */ 47 @Retention(RetentionPolicy.SOURCE) 48 @IntDef({TAB_INDEX_SPEED_DIAL, TAB_INDEX_HISTORY, TAB_INDEX_ALL_CONTACTS, TAB_INDEX_VOICEMAIL}) 49 public @interface TabIndex {} 50 51 public static final int TAB_INDEX_SPEED_DIAL = 0; 52 public static final int TAB_INDEX_HISTORY = 1; 53 public static final int TAB_INDEX_ALL_CONTACTS = 2; 54 public static final int TAB_INDEX_VOICEMAIL = 3; 55 public static final int TAB_COUNT_DEFAULT = 3; 56 public static final int TAB_COUNT_WITH_VOICEMAIL = 4; 57 58 private final List<Fragment> fragments = new ArrayList<>(); 59 private final String[] tabTitles; 60 private final boolean useNewSpeedDialTab; 61 private final boolean useNewCallLogTab; 62 private final boolean useNewContactsTab; 63 private OldSpeedDialFragment oldSpeedDialFragment; 64 private SpeedDialFragment speedDialFragment; 65 private CallLogFragment callLogFragment; 66 private NewCallLogFragment newCallLogFragment; 67 private AllContactsFragment oldContactsFragment; 68 private ContactsFragment contactsFragment; 69 private CallLogFragment voicemailFragment; 70 71 public boolean hasActiveVoicemailProvider; 72 DialtactsPagerAdapter( Context context, FragmentManager fm, String[] tabTitles, boolean hasVoicemailProvider)73 public DialtactsPagerAdapter( 74 Context context, FragmentManager fm, String[] tabTitles, boolean hasVoicemailProvider) { 75 super(fm); 76 useNewSpeedDialTab = 77 ConfigProviderBindings.get(context).getBoolean("enable_new_favorites_tab", false); 78 CallLogFramework callLogFramework = CallLogComponent.get(context).callLogFramework(); 79 useNewCallLogTab = callLogFramework.isNewCallLogEnabled(context); 80 useNewContactsTab = 81 ConfigProviderBindings.get(context).getBoolean("enable_new_contacts_tab", false); 82 this.tabTitles = tabTitles; 83 hasActiveVoicemailProvider = hasVoicemailProvider; 84 fragments.addAll(Collections.nCopies(TAB_COUNT_WITH_VOICEMAIL, null)); 85 } 86 87 @Override getItemId(int position)88 public long getItemId(int position) { 89 return getRtlPosition(position); 90 } 91 92 @Override getItem(int position)93 public Fragment getItem(int position) { 94 LogUtil.d("ViewPagerAdapter.getItem", "position: %d", position); 95 switch (getRtlPosition(position)) { 96 case TAB_INDEX_SPEED_DIAL: 97 if (useNewSpeedDialTab) { 98 if (speedDialFragment == null) { 99 speedDialFragment = SpeedDialFragment.newInstance(); 100 } 101 return speedDialFragment; 102 } else { 103 if (oldSpeedDialFragment == null) { 104 oldSpeedDialFragment = new OldSpeedDialFragment(); 105 } 106 return oldSpeedDialFragment; 107 } 108 case TAB_INDEX_HISTORY: 109 if (useNewCallLogTab) { 110 if (newCallLogFragment == null) { 111 newCallLogFragment = new NewCallLogFragment(); 112 } 113 return newCallLogFragment; 114 } else { 115 if (callLogFragment == null) { 116 callLogFragment = new CallLogFragment(CallLogQueryHandler.CALL_TYPE_ALL); 117 } 118 return callLogFragment; 119 } 120 case TAB_INDEX_ALL_CONTACTS: 121 if (useNewContactsTab) { 122 if (contactsFragment == null) { 123 contactsFragment = new ContactsFragment(); 124 } 125 return contactsFragment; 126 } else { 127 if (oldContactsFragment == null) { 128 oldContactsFragment = new AllContactsFragment(); 129 } 130 return oldContactsFragment; 131 } 132 case TAB_INDEX_VOICEMAIL: 133 if (voicemailFragment == null) { 134 voicemailFragment = new VisualVoicemailCallLogFragment(); 135 LogUtil.v( 136 "ViewPagerAdapter.getItem", 137 "new VisualVoicemailCallLogFragment: %s", 138 voicemailFragment); 139 } 140 return voicemailFragment; 141 default: 142 throw Assert.createIllegalStateFailException("No fragment at position " + position); 143 } 144 } 145 146 @Override instantiateItem(ViewGroup container, int position)147 public Fragment instantiateItem(ViewGroup container, int position) { 148 LogUtil.d("ViewPagerAdapter.instantiateItem", "position: %d", position); 149 // On rotation the FragmentManager handles rotation. Therefore getItem() isn't called. 150 // Copy the fragments that the FragmentManager finds so that we can store them in 151 // instance variables for later. 152 final Fragment fragment = (Fragment) super.instantiateItem(container, position); 153 if (fragment instanceof OldSpeedDialFragment) { 154 oldSpeedDialFragment = (OldSpeedDialFragment) fragment; 155 } else if (fragment instanceof SpeedDialFragment) { 156 speedDialFragment = (SpeedDialFragment) fragment; 157 } else if (fragment instanceof CallLogFragment && position == TAB_INDEX_HISTORY) { 158 callLogFragment = (CallLogFragment) fragment; 159 } else if (fragment instanceof NewCallLogFragment) { 160 newCallLogFragment = (NewCallLogFragment) fragment; 161 } else if (fragment instanceof ContactsFragment) { 162 contactsFragment = (ContactsFragment) fragment; 163 } else if (fragment instanceof AllContactsFragment) { 164 oldContactsFragment = (AllContactsFragment) fragment; 165 } else if (fragment instanceof CallLogFragment && position == TAB_INDEX_VOICEMAIL) { 166 voicemailFragment = (CallLogFragment) fragment; 167 LogUtil.v("ViewPagerAdapter.instantiateItem", voicemailFragment.toString()); 168 } 169 fragments.set(position, fragment); 170 return fragment; 171 } 172 173 /** 174 * When {@link android.support.v4.view.PagerAdapter#notifyDataSetChanged} is called, this method 175 * is called on all pages to determine whether they need to be recreated. When the voicemail tab 176 * is removed, the view needs to be recreated by returning POSITION_NONE. If notifyDataSetChanged 177 * is called for some other reason, the voicemail tab is recreated only if it is active. All other 178 * tabs do not need to be recreated and POSITION_UNCHANGED is returned. 179 */ 180 @Override getItemPosition(Object object)181 public int getItemPosition(Object object) { 182 return !hasActiveVoicemailProvider && fragments.indexOf(object) == TAB_INDEX_VOICEMAIL 183 ? POSITION_NONE 184 : POSITION_UNCHANGED; 185 } 186 187 @Override getCount()188 public int getCount() { 189 return hasActiveVoicemailProvider ? TAB_COUNT_WITH_VOICEMAIL : TAB_COUNT_DEFAULT; 190 } 191 192 @Override getPageTitle(@abIndex int position)193 public CharSequence getPageTitle(@TabIndex int position) { 194 return tabTitles[position]; 195 } 196 getRtlPosition(int position)197 public int getRtlPosition(int position) { 198 if (ViewUtil.isRtl()) { 199 return getCount() - 1 - position; 200 } 201 return position; 202 } 203 removeVoicemailFragment(FragmentManager manager)204 public void removeVoicemailFragment(FragmentManager manager) { 205 if (voicemailFragment != null) { 206 manager.beginTransaction().remove(voicemailFragment).commitAllowingStateLoss(); 207 voicemailFragment = null; 208 } 209 } 210 hasActiveVoicemailProvider()211 public boolean hasActiveVoicemailProvider() { 212 return hasActiveVoicemailProvider; 213 } 214 setHasActiveVoicemailProvider(boolean hasActiveVoicemailProvider)215 public void setHasActiveVoicemailProvider(boolean hasActiveVoicemailProvider) { 216 this.hasActiveVoicemailProvider = hasActiveVoicemailProvider; 217 } 218 } 219