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.Gravity
21 import android.view.ViewGroup
22 import android.view.ViewGroup.LayoutParams.MATCH_PARENT
23 import android.widget.FrameLayout
24 import android.widget.ImageView
25 import android.widget.LinearLayout
26 import android.widget.Space
27 import com.android.launcher3.R
28 import com.android.launcher3.taskbar.TaskbarActivityContext
29 
30 open class PhoneLandscapeNavLayoutter(
31     resources: Resources,
32     navBarContainer: LinearLayout,
33     endContextualContainer: ViewGroup,
34     startContextualContainer: ViewGroup,
35     imeSwitcher: ImageView?,
36     a11yButton: ImageView?,
37     space: Space?
38 ) :
39     AbstractNavButtonLayoutter(
40         resources,
41         navBarContainer,
42         endContextualContainer,
43         startContextualContainer,
44         imeSwitcher,
45         a11yButton,
46         space
47     ) {
48 
layoutButtonsnull49     override fun layoutButtons(context: TaskbarActivityContext, isA11yButtonPersistent: Boolean) {
50         val totalHeight = context.deviceProfile.heightPx
51         val homeButtonHeight =
52             resources.getDimensionPixelSize(R.dimen.taskbar_phone_home_button_size)
53         val roundedCornerContentMargin =
54             resources.getDimensionPixelSize(R.dimen.taskbar_phone_rounded_corner_content_margin)
55         val contentPadding = resources.getDimensionPixelSize(R.dimen.taskbar_phone_content_padding)
56         val contentWidth = totalHeight - roundedCornerContentMargin * 2 - contentPadding * 2
57 
58         // left:back:space(reserved for home):overview:right = 0.25:0.5:1:0.5:0.25
59         val contextualButtonHeight = contentWidth / (0.25f + 0.5f + 1f + 0.5f + 0.25f) * 0.25f
60         val sideButtonHeight = contextualButtonHeight * 2
61         val navButtonContainerHeight = contentWidth - contextualButtonHeight * 2
62 
63         val navContainerParams =
64             FrameLayout.LayoutParams(MATCH_PARENT, navButtonContainerHeight.toInt())
65         navContainerParams.apply {
66             topMargin =
67                 (contextualButtonHeight + contentPadding + roundedCornerContentMargin).toInt()
68             bottomMargin =
69                 (contextualButtonHeight + contentPadding + roundedCornerContentMargin).toInt()
70             marginEnd = 0
71             marginStart = 0
72         }
73 
74         // Ensure order of buttons is correct
75         navButtonContainer.removeAllViews()
76         navButtonContainer.orientation = LinearLayout.VERTICAL
77 
78         addThreeButtons()
79 
80         navButtonContainer.layoutParams = navContainerParams
81         navButtonContainer.gravity = Gravity.CENTER
82 
83         // Add the spaces in between the nav buttons
84         val spaceInBetween =
85             (navButtonContainerHeight - homeButtonHeight - sideButtonHeight * 2) / 2.0f
86         for (i in 0 until navButtonContainer.childCount) {
87             val navButton = navButtonContainer.getChildAt(i)
88             val buttonLayoutParams = navButton.layoutParams as LinearLayout.LayoutParams
89             val margin = (spaceInBetween / 2).toInt()
90             when (i) {
91                 0 -> {
92                     // First button
93                     buttonLayoutParams.bottomMargin = margin
94                     buttonLayoutParams.height = sideButtonHeight.toInt()
95                 }
96                 navButtonContainer.childCount - 1 -> {
97                     // Last button
98                     buttonLayoutParams.topMargin = margin
99                     buttonLayoutParams.height = sideButtonHeight.toInt()
100                 }
101                 else -> {
102                     // other buttons
103                     buttonLayoutParams.topMargin = margin
104                     buttonLayoutParams.bottomMargin = margin
105                     buttonLayoutParams.height = homeButtonHeight
106                 }
107             }
108         }
109 
110         repositionContextualButtons(contextualButtonHeight.toInt())
111     }
112 
addThreeButtonsnull113     open fun addThreeButtons() {
114         // Swap recents and back button
115         navButtonContainer.addView(recentsButton)
116         navButtonContainer.addView(homeButton)
117         navButtonContainer.addView(backButton)
118     }
119 
repositionContextualButtonsnull120     open fun repositionContextualButtons(buttonSize: Int) {
121         endContextualContainer.removeAllViews()
122         startContextualContainer.removeAllViews()
123 
124         val roundedCornerContentMargin =
125             resources.getDimensionPixelSize(R.dimen.taskbar_phone_rounded_corner_content_margin)
126         val contentPadding = resources.getDimensionPixelSize(R.dimen.taskbar_phone_content_padding)
127         repositionContextualContainer(
128             startContextualContainer,
129             buttonSize,
130             roundedCornerContentMargin + contentPadding,
131             0,
132             Gravity.TOP
133         )
134         repositionContextualContainer(
135             endContextualContainer,
136             buttonSize,
137             0,
138             roundedCornerContentMargin + contentPadding,
139             Gravity.BOTTOM
140         )
141 
142         if (imeSwitcher != null) {
143             startContextualContainer.addView(imeSwitcher)
144             imeSwitcher.layoutParams = getParamsToCenterView()
145         }
146         if (a11yButton != null) {
147             startContextualContainer.addView(a11yButton)
148             a11yButton.layoutParams = getParamsToCenterView()
149         }
150         endContextualContainer.addView(space, MATCH_PARENT, MATCH_PARENT)
151     }
152 
repositionContextualContainernull153     override fun repositionContextualContainer(
154         contextualContainer: ViewGroup,
155         buttonSize: Int,
156         barAxisMarginTop: Int,
157         barAxisMarginBottom: Int,
158         gravity: Int
159     ) {
160         val contextualContainerParams = FrameLayout.LayoutParams(MATCH_PARENT, buttonSize)
161         contextualContainerParams.apply {
162             marginStart = 0
163             marginEnd = 0
164             topMargin = barAxisMarginTop
165             bottomMargin = barAxisMarginBottom
166         }
167         contextualContainerParams.gravity = gravity or Gravity.CENTER_HORIZONTAL
168         contextualContainer.layoutParams = contextualContainerParams
169     }
170 }
171