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.car.settings.common; 18 19 import static com.android.car.ui.core.CarUi.requireInsets; 20 import static com.android.car.ui.core.CarUi.requireToolbar; 21 22 import android.car.drivingstate.CarUxRestrictions; 23 import android.car.drivingstate.CarUxRestrictionsManager; 24 import android.content.Context; 25 import android.os.Bundle; 26 import android.view.LayoutInflater; 27 import android.view.View; 28 import android.view.ViewGroup; 29 30 import androidx.annotation.LayoutRes; 31 import androidx.annotation.NonNull; 32 import androidx.annotation.StringRes; 33 import androidx.fragment.app.Fragment; 34 35 import com.android.car.settings.R; 36 import com.android.car.ui.baselayout.Insets; 37 import com.android.car.ui.baselayout.InsetsChangedListener; 38 import com.android.car.ui.toolbar.MenuItem; 39 import com.android.car.ui.toolbar.Toolbar; 40 import com.android.car.ui.toolbar.ToolbarController; 41 42 import java.util.List; 43 44 /** 45 * Base fragment for setting activity. 46 */ 47 public abstract class BaseFragment extends Fragment implements 48 CarUxRestrictionsManager.OnUxRestrictionsChangedListener, InsetsChangedListener { 49 50 /** 51 * Return the {@link FragmentHost}. 52 */ getFragmentHost()53 public final FragmentHost getFragmentHost() { 54 return (FragmentHost) requireActivity(); 55 } 56 57 /** 58 * Assume The activity holds this fragment also implements the UxRestrictionsProvider. 59 * This function should be called after onAttach() 60 */ getCurrentRestrictions()61 protected final CarUxRestrictions getCurrentRestrictions() { 62 return ((UxRestrictionsProvider) getActivity()).getCarUxRestrictions(); 63 } 64 65 /** 66 * Checks if this fragment can be shown or not given the CarUxRestrictions. Default to 67 * {@code false} if UX_RESTRICTIONS_NO_SETUP is set. 68 */ canBeShown(@onNull CarUxRestrictions carUxRestrictions)69 protected boolean canBeShown(@NonNull CarUxRestrictions carUxRestrictions) { 70 return !CarUxRestrictionsHelper.isNoSetup(carUxRestrictions); 71 } 72 73 @Override onUxRestrictionsChanged(CarUxRestrictions restrictionInfo)74 public void onUxRestrictionsChanged(CarUxRestrictions restrictionInfo) { 75 } 76 77 /** 78 * Returns the layout id of the current Fragment. 79 */ 80 @LayoutRes getLayoutId()81 protected abstract int getLayoutId(); 82 83 /** 84 * Returns the string id for the current Fragment title. Subclasses should override this 85 * method to set the title to display. Use {@link #getToolbar().setTitle(CharSequence)} to 86 * update the displayed title while resumed. The default title is the Settings Activity label. 87 */ 88 @StringRes getTitleId()89 protected int getTitleId() { 90 return R.string.settings_label; 91 } 92 93 /** 94 * Returns the MenuItems to display in the toolbar. Subclasses should override this to 95 * add additional buttons, switches, ect. to the toolbar. 96 */ getToolbarMenuItems()97 protected List<MenuItem> getToolbarMenuItems() { 98 return null; 99 } 100 getToolbarState()101 protected Toolbar.State getToolbarState() { 102 return Toolbar.State.SUBPAGE; 103 } 104 getToolbarNavButtonStyle()105 protected Toolbar.NavButtonMode getToolbarNavButtonStyle() { 106 return Toolbar.NavButtonMode.BACK; 107 } 108 getToolbar()109 protected final ToolbarController getToolbar() { 110 return requireToolbar(requireActivity()); 111 } 112 113 @Override onAttach(Context context)114 public void onAttach(Context context) { 115 super.onAttach(context); 116 if (!(getActivity() instanceof FragmentHost)) { 117 throw new IllegalStateException("Must attach to a FragmentHost"); 118 } 119 if (!(getActivity() instanceof UxRestrictionsProvider)) { 120 throw new IllegalStateException("Must attach to a UxRestrictionsProvider"); 121 } 122 } 123 124 @Override onCreateView(@onNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)125 public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, 126 Bundle savedInstanceState) { 127 @LayoutRes int layoutId = getLayoutId(); 128 return inflater.inflate(layoutId, container, false); 129 } 130 131 @Override onActivityCreated(Bundle savedInstanceState)132 public void onActivityCreated(Bundle savedInstanceState) { 133 super.onActivityCreated(savedInstanceState); 134 ToolbarController toolbar = getToolbar(); 135 if (toolbar != null) { 136 List<MenuItem> items = getToolbarMenuItems(); 137 if (items != null) { 138 if (items.size() == 1) { 139 items.get(0).setId(R.id.toolbar_menu_item_0); 140 } else if (items.size() == 2) { 141 items.get(0).setId(R.id.toolbar_menu_item_0); 142 items.get(1).setId(R.id.toolbar_menu_item_1); 143 } 144 } 145 toolbar.setTitle(getTitleId()); 146 toolbar.setMenuItems(items); 147 toolbar.setState(getToolbarState()); 148 toolbar.setNavButtonMode(getToolbarNavButtonStyle()); 149 } 150 } 151 152 @Override onCarUiInsetsChanged(Insets insets)153 public void onCarUiInsetsChanged(Insets insets) { 154 View view = requireView(); 155 View recyclerView = view.findViewById(R.id.recycler_view); 156 if (recyclerView != null) { 157 recyclerView.setPadding(0, insets.getTop(), 0, insets.getBottom()); 158 view.setPadding(insets.getLeft(), 0, insets.getRight(), 0); 159 } else { 160 view.setPadding(insets.getLeft(), insets.getTop(), 161 insets.getRight(), insets.getBottom()); 162 } 163 } 164 165 @Override onStart()166 public void onStart() { 167 super.onStart(); 168 onUxRestrictionsChanged(getCurrentRestrictions()); 169 onCarUiInsetsChanged(requireInsets(requireActivity())); 170 } 171 172 /** 173 * Allow fragment to intercept back press and customize behavior. 174 */ onBackPressed()175 protected void onBackPressed() { 176 getFragmentHost().goBack(); 177 } 178 } 179