Merge "User Switcher: Dynamically set max col" into tm-dev am: 8045e6c8b7

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/16979367

Change-Id: I36680f0eb24dabfe5bbf42ca57d9b5c0430ea7e6
This commit is contained in:
Aaron Liu
2022-02-23 17:26:36 +00:00
committed by Automerger Merge Worker
5 changed files with 125 additions and 15 deletions

View File

@@ -123,6 +123,7 @@
<dimen name="bouncer_user_switcher_icon_size">190dp</dimen> <dimen name="bouncer_user_switcher_icon_size">190dp</dimen>
<dimen name="bouncer_user_switcher_icon_size_plus_margin">222dp</dimen> <dimen name="bouncer_user_switcher_icon_size_plus_margin">222dp</dimen>
<dimen name="user_switcher_fullscreen_horizontal_gap">64dp</dimen>
<dimen name="user_switcher_icon_selected_width">8dp</dimen> <dimen name="user_switcher_icon_selected_width">8dp</dimen>
<dimen name="user_switcher_fullscreen_button_text_size">14sp</dimen> <dimen name="user_switcher_fullscreen_button_text_size">14sp</dimen>
<dimen name="user_switcher_fullscreen_button_padding">12dp</dimen> <dimen name="user_switcher_fullscreen_button_padding">12dp</dimen>

View File

@@ -21,9 +21,8 @@
android:id="@+id/user_switcher_root" android:id="@+id/user_switcher_root"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_marginBottom="40dp" android:layout_marginVertical="40dp"
android:layout_marginEnd="60dp" android:layout_marginHorizontal="60dp">
android:layout_marginStart="60dp">
<androidx.constraintlayout.helper.widget.Flow <androidx.constraintlayout.helper.widget.Flow
android:id="@+id/flow" android:id="@+id/flow"
@@ -36,7 +35,7 @@
app:flow_horizontalBias="0.5" app:flow_horizontalBias="0.5"
app:flow_verticalAlign="center" app:flow_verticalAlign="center"
app:flow_wrapMode="chain" app:flow_wrapMode="chain"
app:flow_horizontalGap="64dp" app:flow_horizontalGap="@dimen/user_switcher_fullscreen_horizontal_gap"
app:flow_verticalGap="44dp" app:flow_verticalGap="44dp"
app:flow_horizontalStyle="packed"/> app:flow_horizontalStyle="packed"/>

View File

@@ -21,8 +21,8 @@
<ImageView <ImageView
android:id="@+id/user_switcher_icon" android:id="@+id/user_switcher_icon"
android:layout_gravity="center" android:layout_gravity="center"
android:layout_width="wrap_content" android:layout_width="@dimen/bouncer_user_switcher_icon_size_plus_margin"
android:layout_height="wrap_content" /> android:layout_height="@dimen/bouncer_user_switcher_icon_size_plus_margin" />
<TextView <TextView
style="@style/Bouncer.UserSwitcher.Spinner.Item" style="@style/Bouncer.UserSwitcher.Spinner.Item"
android:id="@+id/user_switcher_text" android:id="@+id/user_switcher_text"

View File

@@ -35,9 +35,8 @@ import android.widget.AdapterView
import android.widget.ArrayAdapter import android.widget.ArrayAdapter
import android.widget.ImageView import android.widget.ImageView
import android.widget.TextView import android.widget.TextView
import androidx.constraintlayout.helper.widget.Flow import androidx.constraintlayout.helper.widget.Flow
import com.android.internal.annotations.VisibleForTesting
import com.android.internal.util.UserIcons import com.android.internal.util.UserIcons
import com.android.settingslib.Utils import com.android.settingslib.Utils
import com.android.systemui.R import com.android.systemui.R
@@ -47,12 +46,12 @@ import com.android.systemui.plugins.FalsingManager.LOW_PENALTY
import com.android.systemui.statusbar.phone.ShadeController import com.android.systemui.statusbar.phone.ShadeController
import com.android.systemui.statusbar.policy.UserSwitcherController import com.android.systemui.statusbar.policy.UserSwitcherController
import com.android.systemui.statusbar.policy.UserSwitcherController.BaseUserAdapter import com.android.systemui.statusbar.policy.UserSwitcherController.BaseUserAdapter
import com.android.systemui.statusbar.policy.UserSwitcherController.UserRecord
import com.android.systemui.statusbar.policy.UserSwitcherController.USER_SWITCH_DISABLED_ALPHA import com.android.systemui.statusbar.policy.UserSwitcherController.USER_SWITCH_DISABLED_ALPHA
import com.android.systemui.statusbar.policy.UserSwitcherController.USER_SWITCH_ENABLED_ALPHA import com.android.systemui.statusbar.policy.UserSwitcherController.USER_SWITCH_ENABLED_ALPHA
import com.android.systemui.statusbar.policy.UserSwitcherController.UserRecord
import com.android.systemui.util.LifecycleActivity import com.android.systemui.util.LifecycleActivity
import javax.inject.Inject import javax.inject.Inject
import kotlin.math.ceil
private const val USER_VIEW = "user_view" private const val USER_VIEW = "user_view"
@@ -137,6 +136,18 @@ class UserSwitcherActivity @Inject constructor(
return UserIcons.getDefaultUserIcon(resources, item.info.id, false) return UserIcons.getDefaultUserIcon(resources, item.info.id, false)
} }
fun getTotalUserViews(): Int {
return users.count { item ->
!doNotRenderUserView(item)
}
}
fun doNotRenderUserView(item: UserRecord): Boolean {
return item.isAddUser ||
item.isAddSupervisedUser ||
item.isGuest && item.info == null
}
private fun getDrawable(item: UserRecord): Drawable { private fun getDrawable(item: UserRecord): Drawable {
var drawable = if (item.isCurrent && item.isGuest) { var drawable = if (item.isCurrent && item.isGuest) {
getDrawable(R.drawable.ic_avatar_guest_user) getDrawable(R.drawable.ic_avatar_guest_user)
@@ -211,7 +222,8 @@ class UserSwitcherActivity @Inject constructor(
userSwitcherController.init(parent) userSwitcherController.init(parent)
initBroadcastReceiver() initBroadcastReceiver()
buildUserViews()
parent.post { buildUserViews() }
} }
private fun showPopupMenu() { private fun showPopupMenu() {
@@ -272,16 +284,32 @@ class UserSwitcherActivity @Inject constructor(
} }
parent.removeViews(start, count) parent.removeViews(start, count)
addUserRecords.clear() addUserRecords.clear()
val flow = requireViewById<Flow>(R.id.flow) val flow = requireViewById<Flow>(R.id.flow)
val totalWidth = parent.width
val userViewCount = adapter.getTotalUserViews()
val maxColumns = getMaxColumns(userViewCount)
val horizontalGap = resources
.getDimensionPixelSize(R.dimen.user_switcher_fullscreen_horizontal_gap)
val totalWidthOfHorizontalGap = (maxColumns - 1) * horizontalGap
val maxWidgetDiameter = (totalWidth - totalWidthOfHorizontalGap) / maxColumns
flow.setMaxElementsWrap(maxColumns)
for (i in 0 until adapter.getCount()) { for (i in 0 until adapter.getCount()) {
val item = adapter.getItem(i) val item = adapter.getItem(i)
if (item.isAddUser || if (adapter.doNotRenderUserView(item)) {
item.isAddSupervisedUser ||
item.isGuest && item.info == null) {
addUserRecords.add(item) addUserRecords.add(item)
} else { } else {
val userView = adapter.getView(i, null, parent) val userView = adapter.getView(i, null, parent)
userView.requireViewById<ImageView>(R.id.user_switcher_icon).apply {
val lp = layoutParams
if (maxWidgetDiameter < lp.width) {
lp.width = maxWidgetDiameter
lp.height = maxWidgetDiameter
layoutParams = lp
}
}
userView.setId(View.generateViewId()) userView.setId(View.generateViewId())
parent.addView(userView) parent.addView(userView)
@@ -333,6 +361,11 @@ class UserSwitcherActivity @Inject constructor(
broadcastDispatcher.registerReceiver(broadcastReceiver, filter) broadcastDispatcher.registerReceiver(broadcastReceiver, filter)
} }
@VisibleForTesting
fun getMaxColumns(userCount: Int): Int {
return if (userCount < 5) 4 else ceil(userCount / 2.0).toInt()
}
private class ItemAdapter( private class ItemAdapter(
val parentContext: Context, val parentContext: Context,
val resource: Int, val resource: Int,

View File

@@ -0,0 +1,77 @@
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.systemui.user
import android.os.UserManager
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper.RunWithLooper
import android.view.LayoutInflater
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.plugins.FalsingManager
import com.android.systemui.statusbar.phone.ShadeController
import com.android.systemui.statusbar.policy.UserSwitcherController
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.MockitoAnnotations
@SmallTest
@RunWith(AndroidTestingRunner::class)
@RunWithLooper(setAsMainLooper = true)
class UserSwitcherActivityTest : SysuiTestCase() {
@Mock
private lateinit var activity: UserSwitcherActivity
@Mock
private lateinit var userSwitcherController: UserSwitcherController
@Mock
private lateinit var broadcastDispatcher: BroadcastDispatcher
@Mock
private lateinit var layoutInflater: LayoutInflater
@Mock
private lateinit var falsingManager: FalsingManager
@Mock
private lateinit var userManager: UserManager
@Mock
private lateinit var shadeController: ShadeController
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
activity = UserSwitcherActivity(
userSwitcherController,
broadcastDispatcher,
layoutInflater,
falsingManager,
userManager,
shadeController
)
}
@Test
fun testMaxColumns() {
assertThat(activity.getMaxColumns(3)).isEqualTo(4)
assertThat(activity.getMaxColumns(4)).isEqualTo(4)
assertThat(activity.getMaxColumns(5)).isEqualTo(3)
assertThat(activity.getMaxColumns(6)).isEqualTo(3)
assertThat(activity.getMaxColumns(7)).isEqualTo(4)
assertThat(activity.getMaxColumns(9)).isEqualTo(5)
}
}