1 /* 2 * Copyright (C) 2019 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.car.dialer.ui; 18 19 import android.content.Context; 20 import android.graphics.drawable.Drawable; 21 22 import androidx.annotation.Nullable; 23 import androidx.annotation.StringDef; 24 import androidx.fragment.app.Fragment; 25 import androidx.fragment.app.FragmentManager; 26 27 import com.android.car.dialer.R; 28 import com.android.car.dialer.ui.calllog.CallHistoryFragment; 29 import com.android.car.dialer.ui.common.OnItemClickedListener; 30 import com.android.car.dialer.ui.contact.ContactListFragment; 31 import com.android.car.dialer.ui.dialpad.DialpadFragment; 32 import com.android.car.dialer.ui.favorite.FavoriteFragment; 33 import com.android.car.ui.toolbar.Tab; 34 35 import com.google.common.collect.ImmutableMap; 36 37 import java.util.ArrayList; 38 import java.util.HashMap; 39 import java.util.List; 40 import java.util.Map; 41 42 /** 43 * Tab presenting fragments. 44 */ 45 public class TelecomPageTab { 46 47 /** 48 * Note: the strings must be consist with the items in string array tabs_config 49 */ 50 @StringDef({ 51 TelecomPageTab.Page.FAVORITES, 52 TelecomPageTab.Page.CALL_HISTORY, 53 TelecomPageTab.Page.CONTACTS, 54 TelecomPageTab.Page.DIAL_PAD 55 }) 56 public @interface Page { 57 String FAVORITES = "FAVORITE"; 58 String CALL_HISTORY = "CALL_HISTORY"; 59 String CONTACTS = "CONTACTS"; 60 String DIAL_PAD = "DIAL_PAD"; 61 } 62 63 private final Factory mFactory; 64 private Fragment mFragment; 65 private String mFragmentTag; 66 private boolean mWasFragmentRestored; 67 private final Tab mToolbarTab; 68 TelecomPageTab(@ullable Drawable icon, @Nullable String text, @Nullable OnItemClickedListener<TelecomPageTab> listener, Factory factory)69 private TelecomPageTab(@Nullable Drawable icon, @Nullable String text, 70 @Nullable OnItemClickedListener<TelecomPageTab> listener, Factory factory) { 71 mFactory = factory; 72 mToolbarTab = Tab.builder() 73 .setIcon(icon) 74 .setText(text) 75 .setSelectedListener(listener == null 76 ? null 77 : tab -> listener.onItemClicked(this)) 78 .build(); 79 } 80 getToolbarTab()81 public Tab getToolbarTab() { 82 return mToolbarTab; 83 } 84 85 /** 86 * Either restore fragment from saved state or create new instance. 87 */ initFragment(FragmentManager fragmentManager, @Page String page, boolean shouldForceRecreateFragment)88 private void initFragment(FragmentManager fragmentManager, @Page String page, 89 boolean shouldForceRecreateFragment) { 90 mFragmentTag = makeFragmentTag(page); 91 mFragment = fragmentManager.findFragmentByTag(mFragmentTag); 92 if (mFragment == null || shouldForceRecreateFragment) { 93 mFragment = mFactory.createFragment(page); 94 mWasFragmentRestored = false; 95 return; 96 } 97 mWasFragmentRestored = true; 98 } 99 100 /** 101 * Returns true if the fragment for this tab is restored from a saved state. 102 */ wasFragmentRestored()103 public boolean wasFragmentRestored() { 104 return mWasFragmentRestored; 105 } 106 107 /** 108 * Returns the fragment for this tab. 109 */ getFragment()110 public Fragment getFragment() { 111 return mFragment; 112 } 113 114 /** 115 * Returns the fragment tag for this tab. 116 */ getFragmentTag()117 public String getFragmentTag() { 118 return mFragmentTag; 119 } 120 makeFragmentTag(@age String page)121 private String makeFragmentTag(@Page String page) { 122 return String.format("%s:%s", getClass().getSimpleName(), page); 123 } 124 125 /** 126 * Responsible for creating the top tab items and their fragments. 127 */ 128 public static class Factory { 129 130 private static final ImmutableMap<String, Integer> TAB_LABELS = 131 ImmutableMap.<String, Integer>builder() 132 .put(Page.FAVORITES, R.string.favorites_title) 133 .put(Page.CALL_HISTORY, R.string.call_history_title) 134 .put(Page.CONTACTS, R.string.contacts_title) 135 .put(Page.DIAL_PAD, R.string.dialpad_title) 136 .build(); 137 138 private static final ImmutableMap<String, Integer> TAB_ICONS = 139 ImmutableMap.<String, Integer>builder() 140 .put(Page.FAVORITES, R.drawable.ic_favorite) 141 .put(Page.CALL_HISTORY, R.drawable.ic_history) 142 .put(Page.CONTACTS, R.drawable.ic_contact) 143 .put(Page.DIAL_PAD, R.drawable.ic_dialpad) 144 .build(); 145 146 private final FragmentManager mFragmentManager; 147 private final Map<String, Integer> mTabPageIndexMap; 148 private final String[] mTabConfig; 149 private final List<TelecomPageTab> mTabs = new ArrayList<>(); 150 private final OnItemClickedListener<TelecomPageTab> mSelectedListener; 151 Factory(Context context, OnItemClickedListener<TelecomPageTab> listener, FragmentManager fragmentManager)152 public Factory(Context context, 153 OnItemClickedListener<TelecomPageTab> listener, 154 FragmentManager fragmentManager) { 155 mFragmentManager = fragmentManager; 156 mSelectedListener = listener; 157 158 mTabConfig = context.getResources().getStringArray(R.array.tabs_config); 159 160 mTabPageIndexMap = new HashMap<>(); 161 for (int i = 0; i < getTabCount(); i++) { 162 mTabPageIndexMap.put(mTabConfig[i], i); 163 } 164 } 165 createFragment(@age String page)166 private Fragment createFragment(@Page String page) { 167 switch (page) { 168 case Page.FAVORITES: 169 return FavoriteFragment.newInstance(); 170 case Page.CALL_HISTORY: 171 return CallHistoryFragment.newInstance(); 172 case Page.CONTACTS: 173 return ContactListFragment.newInstance(); 174 case Page.DIAL_PAD: 175 return DialpadFragment.newPlaceCallDialpad(); 176 default: 177 throw new UnsupportedOperationException("Tab is not supported."); 178 } 179 } 180 181 /** 182 * Create the tab for the given {@param tabIndex} 183 */ recreateTabs(Context context, boolean forceInit)184 public List<TelecomPageTab> recreateTabs(Context context, boolean forceInit) { 185 mTabs.clear(); 186 for (int i = 0; i < getTabCount(); i++) { 187 String page = mTabConfig[i]; 188 TelecomPageTab telecomPageTab = new TelecomPageTab( 189 context.getDrawable(TAB_ICONS.get(page)), 190 context.getString(TAB_LABELS.get(page)), 191 mSelectedListener, 192 this); 193 telecomPageTab.initFragment(mFragmentManager, page, forceInit); 194 mTabs.add(telecomPageTab); 195 } 196 return mTabs; 197 } 198 getTabCount()199 public int getTabCount() { 200 return mTabConfig.length; 201 } 202 203 /** 204 * Returns the index for the given {@param page} 205 */ getTabIndex(@age String page)206 public int getTabIndex(@Page String page) { 207 return mTabPageIndexMap.getOrDefault(page, -1); 208 } 209 210 /** 211 * Returns the {@link TelecomPageTab} at the given index 212 */ getTab(int index)213 public TelecomPageTab getTab(int index) { 214 return mTabs.get(index); 215 } 216 } 217 } 218