1 /* 2 * Copyright (C) 2018 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 package com.android.wallpaper.picker; 17 18 import static android.view.View.GONE; 19 import static android.view.View.VISIBLE; 20 21 import android.annotation.MenuRes; 22 import android.app.Activity; 23 import android.content.Context; 24 import android.graphics.drawable.Drawable; 25 import android.os.Bundle; 26 import android.text.TextUtils; 27 import android.view.MenuItem; 28 import android.view.View; 29 import android.view.ViewGroup; 30 import android.view.Window; 31 import android.widget.TextView; 32 import android.widget.Toolbar; 33 import android.widget.Toolbar.OnMenuItemClickListener; 34 35 import androidx.annotation.Nullable; 36 import androidx.core.view.WindowCompat; 37 import androidx.core.view.WindowInsetsControllerCompat; 38 39 import com.android.wallpaper.R; 40 import com.android.wallpaper.config.BaseFlags; 41 import com.android.wallpaper.util.ResourceUtils; 42 import com.android.wallpaper.widget.BottomActionBar; 43 44 import com.google.android.material.transition.MaterialSharedAxis; 45 46 /** 47 * Base class for Fragments that own a {@link Toolbar} widget and a {@link BottomActionBar}. 48 * 49 * A Fragment extending this class is expected to have a {@link Toolbar} in its root view, with id 50 * {@link R.id#toolbar}, which can optionally have a TextView with id custom_toolbar_title for 51 * the title. 52 * If the Bundle returned by {@link #createArguments(CharSequence)} is used as Arguments for this 53 * Fragment, the title provided to that method will be used as the Fragment's toolbar title, 54 * otherwise, the value returned by {@link #getDefaultTitle()} (default being {@code null}) will be 55 * used as title. 56 * 57 * @see #setArguments(Bundle) 58 * @see BottomActionBarFragment 59 */ 60 public abstract class AppbarFragment extends BottomActionBarFragment 61 implements OnMenuItemClickListener { 62 63 private static final String ARG_TITLE = "ToolbarFragment.title"; 64 private AppbarFragmentHost mHost; 65 private boolean mUpArrowEnabled; 66 67 /** 68 * Interface to be implemented by an Activity hosting a {@link AppbarFragment}. 69 */ 70 public interface AppbarFragmentHost { 71 /** 72 * Called when a up arrow had been pressed. 73 */ onUpArrowPressed()74 void onUpArrowPressed(); 75 76 /** 77 * Check if it supports up arrow. 78 */ isUpArrowSupported()79 boolean isUpArrowSupported(); 80 } 81 82 @Override onCreate(@ullable Bundle savedInstanceState)83 public void onCreate(@Nullable Bundle savedInstanceState) { 84 super.onCreate(savedInstanceState); 85 if (BaseFlags.get().isPageTransitionsFeatureEnabled(requireContext())) { 86 setEnterTransition(new MaterialSharedAxis(MaterialSharedAxis.X, /* forward */ true)); 87 setReturnTransition(new MaterialSharedAxis(MaterialSharedAxis.X, /* forward */ false)); 88 setExitTransition(new MaterialSharedAxis(MaterialSharedAxis.X, /* forward */ true)); 89 setReenterTransition(new MaterialSharedAxis(MaterialSharedAxis.X, /* forward */ false)); 90 } 91 } 92 93 @Override onAttach(Context context)94 public void onAttach(Context context) { 95 super.onAttach(context); 96 mHost = (AppbarFragmentHost) context; 97 } 98 99 /** 100 * Returns a newly created {@link Bundle} containing the given title as an argument. 101 * If set as a ToolbarFragment's arguments bundle, this will be used to set up the title of 102 * the Toolbar in {@link #setUpToolbar(View)} 103 */ createArguments(CharSequence title)104 protected static Bundle createArguments(CharSequence title) { 105 Bundle args = new Bundle(); 106 args.putCharSequence(ARG_TITLE, title); 107 return args; 108 } 109 110 protected Toolbar mToolbar; 111 private TextView mTitleView; 112 113 /** 114 * Configures a toolbar in the given rootView, with id {@code toolbar} and sets its title to 115 * the value in Arguments or {@link #getDefaultTitle()}. 116 * Default upArrow value is true. 117 */ setUpToolbar(View rootView)118 public void setUpToolbar(View rootView) { 119 setUpToolbar(rootView, /* upArrow= */ true, false); 120 } 121 122 /** 123 * Configures a toolbar in the given rootView, inflating the menu corresponding to the given id 124 * for the toolbar menu. 125 * 126 * @param rootView given root view. 127 * @param upArrow true to enable up arrow feature. 128 * @param transparentToolbar whether the toolbar should be transparent 129 */ setUpToolbar(View rootView, boolean upArrow, boolean transparentToolbar)130 protected void setUpToolbar(View rootView, boolean upArrow, boolean transparentToolbar) { 131 mUpArrowEnabled = upArrow; 132 mToolbar = rootView.findViewById(getToolbarId()); 133 134 mTitleView = mToolbar.findViewById(R.id.custom_toolbar_title); 135 136 if (transparentToolbar) { 137 setToolbarColor(android.R.color.transparent); 138 } 139 setUpStatusBar(isStatusBarLightText()); 140 141 CharSequence title; 142 if (getArguments() != null) { 143 title = getArguments().getCharSequence(ARG_TITLE, getDefaultTitle()); 144 } else { 145 title = getDefaultTitle(); 146 } 147 if (!TextUtils.isEmpty(title)) { 148 setTitle(title); 149 } 150 151 if (upArrow && mHost.isUpArrowSupported()) { 152 setUpUpArrow(); 153 } 154 } 155 156 /** 157 * Configures the menu in the toolbar. 158 * 159 * @param menuResId the resource id of the menu 160 */ setUpToolbarMenu(@enuRes int menuResId)161 public void setUpToolbarMenu(@MenuRes int menuResId) { 162 mToolbar.inflateMenu(menuResId); 163 mToolbar.setOnMenuItemClickListener(this); 164 } 165 setUpToolbarMenuClickListener(int menuItemResId, View.OnClickListener listener)166 protected void setUpToolbarMenuClickListener(int menuItemResId, View.OnClickListener listener) { 167 MenuItem menuItem = mToolbar.getMenu().findItem(menuItemResId); 168 menuItem.getActionView().setOnClickListener(listener); 169 } 170 getToolbarId()171 protected int getToolbarId() { 172 return R.id.toolbar; 173 } 174 setUpStatusBar(boolean shouldUseLightText)175 protected void setUpStatusBar(boolean shouldUseLightText) { 176 Activity activity = getActivity(); 177 if (activity == null) { 178 return; 179 } 180 Window window = activity.getWindow(); 181 WindowInsetsControllerCompat windowInsetsController = 182 WindowCompat.getInsetsController(window, window.getDecorView()); 183 windowInsetsController.setAppearanceLightStatusBars(!shouldUseLightText); 184 } 185 isStatusBarLightText()186 protected boolean isStatusBarLightText() { 187 return getResources().getBoolean(R.bool.isFragmentStatusBarLightText); 188 } 189 getToolbarTextColor()190 protected int getToolbarTextColor() { 191 return ResourceUtils.getColorAttr(getActivity(), android.R.attr.textColorPrimary); 192 } 193 194 /** 195 * Set up arrow feature status to enabled or not. Enable it for updating 196 * onBottomActionBarReady() while initializing without toolbar setup. 197 * 198 * @param upArrow true to enable up arrow feature. 199 */ setUpArrowEnabled(boolean upArrow)200 public void setUpArrowEnabled(boolean upArrow) { 201 mUpArrowEnabled = upArrow; 202 } 203 setUpUpArrow()204 private void setUpUpArrow() { 205 Drawable backIcon = getResources().getDrawable(R.drawable.material_ic_arrow_back_black_24, 206 null).mutate(); 207 backIcon.setAutoMirrored(true); 208 backIcon.setTint(getToolbarTextColor()); 209 mToolbar.setNavigationIcon(backIcon); 210 mToolbar.setNavigationContentDescription(R.string.bottom_action_bar_back); 211 mToolbar.setNavigationOnClickListener(v -> mHost.onUpArrowPressed()); 212 } 213 214 /** 215 * Configures a toolbar in the given rootView, inflating the menu corresponding to the given id 216 * for the toolbar menu. 217 * Override {@link #onMenuItemClick(MenuItem)} to listen to item click events. 218 * @see #setUpToolbar(View) 219 */ setUpToolbar(View rootView, @MenuRes int menuResId)220 public void setUpToolbar(View rootView, @MenuRes int menuResId) { 221 setUpToolbar(rootView); 222 setUpToolbarMenu(menuResId); 223 } 224 setToolbarColor(int colorId)225 protected void setToolbarColor(int colorId) { 226 mToolbar.setBackgroundResource(colorId); 227 ((ViewGroup) mToolbar.getParent()).setBackgroundResource(colorId); 228 } 229 230 /** 231 * Provides a title for this Fragment's toolbar to be used if none is found in 232 * {@link #getArguments()}. 233 * Default implementation returns {@code null}. 234 */ getDefaultTitle()235 public CharSequence getDefaultTitle() { 236 return null; 237 } 238 getAccessibilityTitle()239 protected String getAccessibilityTitle() { 240 return null; 241 } 242 setTitle(CharSequence title)243 protected void setTitle(CharSequence title) { 244 if (mToolbar == null) { 245 return; 246 } 247 if (mTitleView != null) { 248 mToolbar.setTitle(null); 249 mTitleView.setText(title); 250 mTitleView.setTextColor(getToolbarTextColor()); 251 } else { 252 mToolbar.setTitle(title); 253 mToolbar.setTitleTextColor(getToolbarTextColor()); 254 } 255 256 // Set Activity title to make TalkBack announce title after updating toolbar title. 257 if (getActivity() != null) { 258 String accessibilityTitle = getAccessibilityTitle(); 259 getActivity().setTitle(TextUtils.isEmpty(accessibilityTitle) ? title 260 : accessibilityTitle); 261 } 262 } 263 264 @Override onBottomActionBarReady(BottomActionBar bottomActionBar)265 protected void onBottomActionBarReady(BottomActionBar bottomActionBar) { 266 bottomActionBar.setBackButtonVisibility( 267 mUpArrowEnabled && mHost.isUpArrowSupported() ? GONE : VISIBLE); 268 super.onBottomActionBarReady(bottomActionBar); 269 } 270 271 @Override onMenuItemClick(MenuItem item)272 public boolean onMenuItemClick(MenuItem item) { 273 return false; 274 } 275 } 276