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 android.app.Activity; 19 20 import androidx.annotation.NonNull; 21 import androidx.annotation.Nullable; 22 23 import com.android.car.ui.baselayout.Insets; 24 import com.android.car.ui.baselayout.InsetsChangedListener; 25 import com.android.car.ui.toolbar.ToolbarController; 26 27 import java.lang.reflect.Method; 28 29 /** 30 * Public interface for general CarUi static functions. 31 */ 32 public class CarUi { 33 34 /** Prevent instantiating this class */ CarUi()35 private CarUi() {} 36 37 /** 38 * Gets the {@link ToolbarController} for an activity. Requires that the Activity uses 39 * Theme.CarUi.WithToolbar, or otherwise sets carUiBaseLayout and carUiToolbar to true. 40 * 41 * See also: {@link #requireToolbar(Activity)} 42 */ 43 @Nullable getToolbar(Activity activity)44 public static ToolbarController getToolbar(Activity activity) { 45 BaseLayoutController controller = getBaseLayoutController(activity); 46 if (controller != null) { 47 return controller.getToolbarController(); 48 } 49 return null; 50 } 51 52 /** 53 * Gets the {@link ToolbarController} for an activity. Requires that the Activity uses 54 * Theme.CarUi.WithToolbar, or otherwise sets carUiBaseLayout and carUiToolbar to true. 55 * 56 * <p>See also: {@link #getToolbar(Activity)} 57 * 58 * @throws IllegalArgumentException When the CarUi Toolbar cannot be found. 59 */ 60 @NonNull requireToolbar(Activity activity)61 public static ToolbarController requireToolbar(Activity activity) { 62 ToolbarController result = getToolbar(activity); 63 if (result == null) { 64 throw new IllegalArgumentException("Activity " + activity 65 + " does not have a CarUi Toolbar!" 66 + " Are you using Theme.CarUi.WithToolbar?"); 67 } 68 69 return result; 70 } 71 72 /** 73 * Registering a listener to receive the InsetsChanged updates instead of the Activity. 74 */ replaceInsetsChangedListenerWith(Activity activity, InsetsChangedListener listener)75 public static void replaceInsetsChangedListenerWith(Activity activity, 76 InsetsChangedListener listener) { 77 BaseLayoutController controller = getBaseLayoutController(activity); 78 if (controller != null) { 79 controller.replaceInsetsChangedListenerWith(listener); 80 } 81 } 82 83 /** 84 * Gets the current {@link Insets} of the given {@link Activity}. Only applies to Activities 85 * using the base layout, ie have the theme attribute "carUiBaseLayout" set to true. 86 * 87 * <p>Note that you likely don't want to use this without also using 88 * {@link com.android.car.ui.baselayout.InsetsChangedListener}, as without it the Insets 89 * will automatically be applied to your Activity's content view. 90 */ 91 @Nullable getInsets(Activity activity)92 public static Insets getInsets(Activity activity) { 93 BaseLayoutController controller = getBaseLayoutController(activity); 94 if (controller != null) { 95 return controller.getInsets(); 96 } 97 return null; 98 } 99 100 /** 101 * Gets the current {@link Insets} of the given {@link Activity}. Only applies to Activities 102 * using the base layout, ie have the theme attribute "carUiBaseLayout" set to true. 103 * 104 * <p>Note that you likely don't want to use this without also using 105 * {@link com.android.car.ui.baselayout.InsetsChangedListener}, as without it the Insets 106 * will automatically be applied to your Activity's content view. 107 * 108 * @throws IllegalArgumentException When the activity is not using base layouts. 109 */ 110 @NonNull requireInsets(Activity activity)111 public static Insets requireInsets(Activity activity) { 112 Insets result = getInsets(activity); 113 if (result == null) { 114 throw new IllegalArgumentException("Activity " + activity 115 + " does not have a base layout!" 116 + " Are you using Theme.CarUi.WithToolbar or Theme.CarUi.NoToolbar?"); 117 } 118 119 return result; 120 } 121 getBaseLayoutController(Activity activity)122 /* package */ static BaseLayoutController getBaseLayoutController(Activity activity) { 123 if (activity.getClassLoader().equals(CarUi.class.getClassLoader())) { 124 return BaseLayoutController.getBaseLayout(activity); 125 } else { 126 // Note: (b/156532465) 127 // The usage of the alternate classloader is to accommodate GMSCore. 128 // Some activities are loaded dynamically from external modules. 129 try { 130 Class baseLayoutControllerClass = activity.getClassLoader() 131 .loadClass(BaseLayoutController.class.getName()); 132 Method method = baseLayoutControllerClass 133 .getDeclaredMethod("getBaseLayout", Activity.class); 134 return (BaseLayoutController) method.invoke(null, activity); 135 } catch (ReflectiveOperationException e) { 136 throw new RuntimeException(e); 137 } 138 } 139 } 140 } 141