1 /* 2 * Copyright (C) 2022 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.launcher3.taskbar.navbutton 18 19 import android.content.res.Resources 20 import android.view.Surface.ROTATION_90 21 import android.view.Surface.Rotation 22 import android.view.ViewGroup 23 import android.widget.ImageView 24 import android.widget.LinearLayout 25 import android.widget.Space 26 import com.android.launcher3.DeviceProfile 27 import com.android.launcher3.taskbar.TaskbarActivityContext 28 import com.android.launcher3.taskbar.navbutton.LayoutResourceHelper.ID_END_CONTEXTUAL_BUTTONS 29 import com.android.launcher3.taskbar.navbutton.LayoutResourceHelper.ID_END_NAV_BUTTONS 30 import com.android.launcher3.taskbar.navbutton.LayoutResourceHelper.ID_START_CONTEXTUAL_BUTTONS 31 import com.android.launcher3.taskbar.navbutton.NavButtonLayoutFactory.Companion 32 import com.android.launcher3.taskbar.navbutton.NavButtonLayoutFactory.NavButtonLayoutter 33 34 /** 35 * Select the correct layout for nav buttons 36 * 37 * Since layouts are done dynamically for the nav buttons on Taskbar, this class returns a 38 * corresponding [NavButtonLayoutter] via [Companion.getUiLayoutter] that can help position the 39 * buttons based on the current [DeviceProfile] 40 */ 41 class NavButtonLayoutFactory { 42 companion object { 43 /** 44 * Get the correct instance of [NavButtonLayoutter] 45 * 46 * No layouts supported for configurations where: 47 * * taskbar isn't showing AND 48 * * the device is not in [phoneMode] OR 49 * * phone is showing 50 * * device is using gesture navigation 51 * 52 * @param navButtonsView ViewGroup that contains start, end, nav button ViewGroups 53 * @param isKidsMode no-op when taskbar is hidden/not showing 54 * @param isInSetup no-op when taskbar is hidden/not showing 55 * @param phoneMode refers to the device using the taskbar window on phones 56 * @param isThreeButtonNav are no-ops when taskbar is present/showing 57 */ getUiLayoutternull58 fun getUiLayoutter( 59 deviceProfile: DeviceProfile, 60 navButtonsView: NearestTouchFrame, 61 imeSwitcher: ImageView?, 62 a11yButton: ImageView?, 63 space: Space?, 64 resources: Resources, 65 isKidsMode: Boolean, 66 isInSetup: Boolean, 67 isThreeButtonNav: Boolean, 68 phoneMode: Boolean, 69 @Rotation surfaceRotation: Int 70 ): NavButtonLayoutter { 71 val navButtonContainer = 72 navButtonsView.requireViewById<LinearLayout>(ID_END_NAV_BUTTONS) 73 val endContextualContainer = 74 navButtonsView.requireViewById<ViewGroup>(ID_END_CONTEXTUAL_BUTTONS) 75 val startContextualContainer = 76 navButtonsView.requireViewById<ViewGroup>(ID_START_CONTEXTUAL_BUTTONS) 77 val isPhoneNavMode = phoneMode && isThreeButtonNav 78 val isPhoneGestureMode = phoneMode && !isThreeButtonNav 79 return when { 80 isPhoneNavMode -> { 81 if (!deviceProfile.isLandscape) { 82 navButtonsView.setIsVertical(false) 83 PhonePortraitNavLayoutter( 84 resources, 85 navButtonContainer, 86 endContextualContainer, 87 startContextualContainer, 88 imeSwitcher, 89 a11yButton, 90 space 91 ) 92 } else if (surfaceRotation == ROTATION_90) { 93 navButtonsView.setIsVertical(true) 94 PhoneLandscapeNavLayoutter( 95 resources, 96 navButtonContainer, 97 endContextualContainer, 98 startContextualContainer, 99 imeSwitcher, 100 a11yButton, 101 space 102 ) 103 } else { 104 navButtonsView.setIsVertical(true) 105 PhoneSeascapeNavLayoutter( 106 resources, 107 navButtonContainer, 108 endContextualContainer, 109 startContextualContainer, 110 imeSwitcher, 111 a11yButton, 112 space 113 ) 114 } 115 } 116 isPhoneGestureMode -> { 117 PhoneGestureLayoutter( 118 resources, 119 navButtonsView, 120 navButtonContainer, 121 endContextualContainer, 122 startContextualContainer, 123 imeSwitcher, 124 a11yButton, 125 space 126 ) 127 } 128 deviceProfile.isTaskbarPresent -> { 129 return when { 130 isInSetup -> { 131 SetupNavLayoutter( 132 resources, 133 navButtonsView, 134 navButtonContainer, 135 endContextualContainer, 136 startContextualContainer, 137 imeSwitcher, 138 a11yButton, 139 space 140 ) 141 } 142 isKidsMode -> { 143 KidsNavLayoutter( 144 resources, 145 navButtonContainer, 146 endContextualContainer, 147 startContextualContainer, 148 imeSwitcher, 149 a11yButton, 150 space 151 ) 152 } 153 else -> 154 TaskbarNavLayoutter( 155 resources, 156 navButtonContainer, 157 endContextualContainer, 158 startContextualContainer, 159 imeSwitcher, 160 a11yButton, 161 space 162 ) 163 } 164 } 165 else -> error("No layoutter found") 166 } 167 } 168 } 169 170 /** Lays out and provides access to the home, recents, and back buttons for various mischief */ 171 interface NavButtonLayoutter { layoutButtonsnull172 fun layoutButtons(context: TaskbarActivityContext, isA11yButtonPersistent: Boolean) 173 } 174 } 175