• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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.car.ui.core;
17 
18 import static com.android.car.ui.core.BaseLayoutController.getBaseLayoutController;
19 
20 import android.app.Activity;
21 import android.content.Context;
22 import android.view.View;
23 
24 import androidx.annotation.NonNull;
25 import androidx.annotation.Nullable;
26 import androidx.recyclerview.widget.RecyclerView;
27 
28 import com.android.car.ui.R;
29 import com.android.car.ui.baselayout.Insets;
30 import com.android.car.ui.baselayout.InsetsChangedListener;
31 import com.android.car.ui.recyclerview.CarUiListItem;
32 import com.android.car.ui.sharedlibrarysupport.SharedLibraryFactorySingleton;
33 import com.android.car.ui.toolbar.ToolbarController;
34 
35 import java.util.List;
36 import java.util.Objects;
37 
38 /**
39  * Public interface for general CarUi static functions.
40  */
41 public class CarUi {
42 
43     /** Prevent instantiating this class */
CarUi()44     private CarUi() {}
45 
46     /**
47      * Gets a CarUi component, such as {@link com.android.car.ui.button.CarUiButton}, from the
48      * view hierarchy. The interfaces for these components don't extend View, so you can't
49      * get them through findViewById().
50      *
51      * @param view The parent view. Its descendants will be searched for the component.
52      * @param id The id of the component.
53      * @param <T> The resulting type of the component, such as
54      *            {@link com.android.car.ui.button.CarUiButton}
55      * @return The component found, or null.
56      */
57     @Nullable
58     @SuppressWarnings({"unchecked", "TypeParameterUnusedInFormals"})
findCarUiComponentById(@ullable View view, int id)59     public static <T> T findCarUiComponentById(@Nullable View view, int id) {
60         if (view == null) {
61             return null;
62         }
63         View componentView = view.findViewById(id);
64         return componentView != null
65                 ? (T) componentView.getTag(R.id.car_ui_component_reference)
66                 : null;
67     }
68 
69     /**
70      * Same as {@link #findCarUiComponentById(View, int)}, but will throw an exception
71      * if the result is null.
72      */
73     @NonNull
requireCarUiComponentById(View view, int id)74     public static <T> T requireCarUiComponentById(View view, int id) {
75         return Objects.requireNonNull(findCarUiComponentById(view, id));
76     }
77 
78     /**
79      * Gets the {@link ToolbarController} for an activity. Requires that the Activity uses
80      * Theme.CarUi.WithToolbar, or otherwise sets carUiBaseLayout and carUiToolbar to true.
81      *
82      * See also: {@link #requireToolbar(Activity)}
83      */
84     @Nullable
getToolbar(@ullable Activity activity)85     public static ToolbarController getToolbar(@Nullable Activity activity) {
86         BaseLayoutController controller = getBaseLayoutController(activity);
87         if (controller != null) {
88             return controller.getToolbarController();
89         }
90         return null;
91     }
92 
93     /**
94      * Use this method to create an instance of a {@link RecyclerView.Adapter} for a list of {@link
95      * CarUiListItem} objects.
96      */
createListItemAdapter( Context context, List<? extends CarUiListItem> items)97     public static RecyclerView.Adapter<? extends RecyclerView.ViewHolder> createListItemAdapter(
98             Context context, List<? extends CarUiListItem> items) {
99         return SharedLibraryFactorySingleton.get(context).createListItemAdapter(items);
100     }
101 
102 
103     /**
104      * Gets the {@link ToolbarController} for an activity. Requires that the Activity uses
105      * Theme.CarUi.WithToolbar, or otherwise sets carUiBaseLayout and carUiToolbar to true.
106      *
107      * <p>See also: {@link #getToolbar(Activity)}
108      *
109      * @throws IllegalArgumentException When the CarUi Toolbar cannot be found.
110      */
111     @NonNull
requireToolbar(@onNull Activity activity)112     public static ToolbarController requireToolbar(@NonNull Activity activity) {
113         ToolbarController result = getToolbar(activity);
114         if (result == null) {
115             throw new IllegalArgumentException("Activity " + activity
116                     + " does not have a CarUi Toolbar!"
117                     + " Are you using Theme.CarUi.WithToolbar?");
118         }
119 
120         return result;
121     }
122 
123     /**
124      * Registering a listener to receive the InsetsChanged updates instead of the Activity.
125      */
replaceInsetsChangedListenerWith(Activity activity, InsetsChangedListener listener)126     public static void replaceInsetsChangedListenerWith(Activity activity,
127             InsetsChangedListener listener) {
128         BaseLayoutController controller = getBaseLayoutController(activity);
129         if (controller != null) {
130             controller.replaceInsetsChangedListenerWith(listener);
131         }
132     }
133 
134     /**
135      * Gets the current {@link Insets} of the given {@link Activity}. Only applies to Activities
136      * using the base layout, ie have the theme attribute "carUiBaseLayout" set to true.
137      *
138      * <p>Note that you likely don't want to use this without also using
139      * {@link com.android.car.ui.baselayout.InsetsChangedListener}, as without it the Insets
140      * will automatically be applied to your Activity's content view.
141      */
142     @Nullable
getInsets(@ullable Activity activity)143     public static Insets getInsets(@Nullable Activity activity) {
144         BaseLayoutController controller = getBaseLayoutController(activity);
145         if (controller != null) {
146             return controller.getInsets();
147         }
148         return null;
149     }
150 
151     /**
152      * Gets the current {@link Insets} of the given {@link Activity}. Only applies to Activities
153      * using the base layout, ie have the theme attribute "carUiBaseLayout" set to true.
154      *
155      * <p>Note that you likely don't want to use this without also using
156      * {@link com.android.car.ui.baselayout.InsetsChangedListener}, as without it the Insets
157      * will automatically be applied to your Activity's content view.
158      *
159      * @throws IllegalArgumentException When the activity is not using base layouts.
160      */
161     @NonNull
requireInsets(@onNull Activity activity)162     public static Insets requireInsets(@NonNull Activity activity) {
163         Insets result = getInsets(activity);
164         if (result == null) {
165             throw new IllegalArgumentException("Activity " + activity
166                     + " does not have a base layout!"
167                     + " Are you using Theme.CarUi.WithToolbar or Theme.CarUi.NoToolbar?");
168         }
169 
170         return result;
171     }
172 
173     /**
174      * Most apps should not use this method, but instead rely on CarUi automatically
175      * installing the base layout into their activities. See {@link #requireToolbar(Activity)}.
176      *
177      * This method installs the base layout *around* the provided view. As a result, this view
178      * must have a parent ViewGroup.
179      *
180      * When using this method, you can't use the other activity-based methods.
181      * ({@link #requireToolbar(Activity)}, {@link #requireInsets(Activity)}, ect.)
182      *
183      * @see #installBaseLayoutAround(View, InsetsChangedListener, boolean, boolean)
184      *
185      * @param view The view to wrap inside a base layout.
186      * @param hasToolbar if there should be a toolbar in the base layout.
187      * @return The {@link ToolbarController}, which will be null if hasToolbar is false.
188      */
189     @Nullable
installBaseLayoutAround( View view, InsetsChangedListener insetsChangedListener, boolean hasToolbar)190     public static ToolbarController installBaseLayoutAround(
191             View view,
192             InsetsChangedListener insetsChangedListener,
193             boolean hasToolbar) {
194         return installBaseLayoutAround(view, insetsChangedListener, hasToolbar, true);
195     }
196 
197     /**
198      * Most apps should not use this method, but instead rely on CarUi automatically
199      * installing the base layout into their activities. See {@link #requireToolbar(Activity)}.
200      *
201      * This method installs the base layout *around* the provided view. As a result, this view
202      * must have a parent ViewGroup.
203      *
204      * When using this method, you can't use the other activity-based methods.
205      * ({@link #requireToolbar(Activity)}, {@link #requireInsets(Activity)}, ect.)
206      *
207      * @param view The view to wrap inside a base layout.
208      * @param hasToolbar if there should be a toolbar in the base layout.
209      * @param fullscreen A hint specifying whether this view we're installing around takes up
210      *                   the whole screen or not. Used to know if putting decorations around
211      *                   the edges is appropriate.
212      * @return The {@link ToolbarController}, which will be null if hasToolbar is false.
213      */
214     @Nullable
installBaseLayoutAround( View view, InsetsChangedListener insetsChangedListener, boolean hasToolbar, boolean fullscreen)215     public static ToolbarController installBaseLayoutAround(
216             View view,
217             InsetsChangedListener insetsChangedListener,
218             boolean hasToolbar,
219             boolean fullscreen) {
220         return SharedLibraryFactorySingleton.get(view.getContext())
221                 .installBaseLayoutAround(view, insetsChangedListener, hasToolbar, fullscreen);
222     }
223 }
224