• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 android.annotation.NonNull;
20 import android.car.drivingstate.CarUxRestrictions;
21 import android.content.Context;
22 import android.os.Bundle;
23 import android.support.annotation.LayoutRes;
24 import android.support.annotation.StringRes;
25 import android.support.v4.app.Fragment;
26 import android.support.v7.app.ActionBar;
27 import android.support.v7.app.AppCompatActivity;
28 import android.support.v7.widget.Toolbar;
29 import android.view.LayoutInflater;
30 import android.view.View;
31 import android.view.ViewGroup;
32 import android.widget.TextView;
33 
34 import com.android.car.settings.R;
35 
36 import java.util.Set;
37 
38 /**
39  * Base fragment for setting activity.
40  */
41 public abstract class BaseFragment extends Fragment {
42     public static final String EXTRA_TITLE_ID = "extra_title_id";
43     public static final String EXTRA_LAYOUT = "extra_layout";
44     public static final String EXTRA_ACTION_BAR_LAYOUT = "extra_action_bar_layout";
45     /**
46      * For indicating a fragment is running in Setup Wizard
47      */
48     public static final String EXTRA_RUNNING_IN_SETUP_WIZARD = "extra_running_in_setup_wizard";
49 
50     /**
51      * Controls the transition of fragment.
52      */
53     public interface FragmentController {
54         /**
55          * Launches fragment in the main container of current activity.
56          */
launchFragment(BaseFragment fragment)57         void launchFragment(BaseFragment fragment);
58 
59         /**
60          * Pops the top off the fragment stack.
61          * @return {@code false} if there's no stack to pop, {@code true} otherwise
62          */
goBack()63         void goBack();
64 
65         /**
66          * Shows a message that current feature is not available when driving.
67          */
showDOBlockingMessage()68         void showDOBlockingMessage();
69     }
70 
71     /**
72      * Provides current CarUxRestrictions.
73      */
74     public interface UXRestrictionsProvider {
75 
76         /**
77          * Fetches current CarUxRestrictions
78          */
79         @NonNull
getCarUxRestrictions()80         CarUxRestrictions getCarUxRestrictions();
81     }
82 
83     @LayoutRes
84     protected int mLayout;
85 
86     @LayoutRes
87     private int mActionBarLayout;
88 
89     @StringRes
90     private int mTitleId;
91 
92     /**
93      * Assume The activity holds this fragment also implements the FragmentController.
94      * This function should be called after onAttach()
95      */
getFragmentController()96     public final FragmentController getFragmentController() {
97         return (FragmentController) getActivity();
98     }
99 
100     /**
101      * Assume The activity holds this fragment also implements the UXRestrictionsProvider.
102      * This function should be called after onAttach()
103      */
getCurrentRestrictions()104     protected final CarUxRestrictions getCurrentRestrictions() {
105         return ((UXRestrictionsProvider) getActivity()).getCarUxRestrictions();
106     }
107 
getBundle()108     protected static Bundle getBundle() {
109         Bundle bundle = new Bundle();
110         bundle.putInt(EXTRA_ACTION_BAR_LAYOUT, R.layout.action_bar);
111         return bundle;
112     }
113 
114     /**
115      * Checks if this fragment can be shown or not given the CarUxRestrictions. Default to
116      * {@code false} if UX_RESTRICTIONS_NO_SETUP is set.
117      */
canBeShown(@onNull CarUxRestrictions carUxRestrictions)118     protected boolean canBeShown(@NonNull CarUxRestrictions carUxRestrictions) {
119         return !CarUxRestrictionsHelper.isNoSetup(carUxRestrictions);
120     }
121 
122     /**
123      * Notifies the fragment with the latest CarUxRestrictions change.
124      */
onUxRestrictionChanged(@onNull CarUxRestrictions carUxRestrictions)125     protected void onUxRestrictionChanged(@NonNull CarUxRestrictions carUxRestrictions) {
126     }
127 
128     @Override
onAttach(Context context)129     public void onAttach(Context context) {
130         super.onAttach(context);
131         if (!(getActivity() instanceof FragmentController)) {
132             throw new IllegalArgumentException("Must attach to an FragmentController");
133         }
134         if (!(getActivity() instanceof UXRestrictionsProvider)) {
135             throw new IllegalArgumentException("Must attach to an UXRestrictionsProvider");
136         }
137     }
138 
139     @Override
onCreate(Bundle savedInstanceState)140     public void onCreate(Bundle savedInstanceState) {
141         super.onCreate(savedInstanceState);
142         Set<String> extraKeys = getArguments().keySet();
143         if (extraKeys.contains(EXTRA_ACTION_BAR_LAYOUT)) {
144             mActionBarLayout = getArguments().getInt(EXTRA_ACTION_BAR_LAYOUT);
145         } else {
146             throw new IllegalArgumentException("must specify a actionBar layout");
147         }
148         if (extraKeys.contains(EXTRA_LAYOUT)) {
149             mLayout = getArguments().getInt(EXTRA_LAYOUT);
150         } else {
151             throw new IllegalArgumentException("must specify a layout");
152         }
153         if (extraKeys.contains(EXTRA_TITLE_ID)) {
154             mTitleId = getArguments().getInt(EXTRA_TITLE_ID);
155         } else {
156             throw new IllegalArgumentException("must specify a title");
157         }
158     }
159 
160     @Override
onStart()161     public void onStart() {
162         super.onStart();
163         onUxRestrictionChanged(getCurrentRestrictions());
164     }
165 
166     /**
167      * Should be used to override fragment's title.
168      * Should be called after {@code super.onActivityCreated}, so that it's called AFTER the default title
169      * setter.
170      *
171      * @param title CharSequence to set as the new title.
172      */
setTitle(CharSequence title)173     protected final void setTitle(CharSequence title) {
174         TextView titleView = getActivity().findViewById(R.id.title);
175         titleView.setText(title);
176     }
177 
178     /**
179      * Allow fragment to intercept back press and customize behavior.
180      */
onBackPressed()181     protected void onBackPressed() {
182         getFragmentController().goBack();
183     }
184 
185     @Override
onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)186     public View onCreateView(LayoutInflater inflater, ViewGroup container,
187             Bundle savedInstanceState) {
188         return inflater.inflate(mLayout, container, false);
189     }
190 
191     @Override
onActivityCreated(Bundle savedInstanceState)192     public void onActivityCreated(Bundle savedInstanceState) {
193         super.onActivityCreated(savedInstanceState);
194         ActionBar actionBar = ((AppCompatActivity) getActivity()).getSupportActionBar();
195         actionBar.setDisplayHomeAsUpEnabled(false);
196         actionBar.setCustomView(mActionBarLayout);
197         actionBar.setDisplayShowCustomEnabled(true);
198         // make the toolbar take the whole width.
199         Toolbar toolbar = (Toolbar) actionBar.getCustomView().getParent();
200         toolbar.setPadding(0, 0, 0, 0);
201         getActivity().findViewById(R.id.action_bar_icon_container).setOnClickListener(
202                 v -> onBackPressed());
203         TextView titleView = getActivity().findViewById(R.id.title);
204         titleView.setText(mTitleId);
205     }
206 }
207