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