Apply dialog style to User switcher dialog.
Apply the unified style and set just the inner content, relying on the default title and buttons. Also, fix using the vertical spacing in PseudoGridView. Test: manual Test: atest UserSwitchDialogControllerTest Bug: 203666386 Change-Id: If6a0220979d9f9df584c29f4adce317341577cf4 Merged-In: If6a0220979d9f9df584c29f4adce317341577cf4
This commit is contained in:
@@ -22,6 +22,6 @@
|
||||
xmlns:sysui="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
sysui:verticalSpacing="4dp"
|
||||
sysui:verticalSpacing="20dp"
|
||||
sysui:horizontalSpacing="4dp"
|
||||
style="@style/UserDetailView" />
|
||||
@@ -24,8 +24,6 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:gravity="top|center_horizontal"
|
||||
android:paddingTop="16dp"
|
||||
android:minHeight="112dp"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
android:focusable="true"
|
||||
|
||||
@@ -15,75 +15,19 @@
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
<FrameLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:sysui="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="24dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
>
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="0dp"
|
||||
android:textAlignment="center"
|
||||
android:text="@string/qs_user_switch_dialog_title"
|
||||
android:textAppearance="@style/TextAppearance.Dialog.Title"
|
||||
android:layout_marginBottom="32dp"
|
||||
sysui:layout_constraintTop_toTopOf="parent"
|
||||
sysui:layout_constraintStart_toStartOf="parent"
|
||||
sysui:layout_constraintEnd_toEndOf="parent"
|
||||
sysui:layout_constraintBottom_toTopOf="@id/grid"
|
||||
/>
|
||||
|
||||
>
|
||||
<com.android.systemui.qs.PseudoGridView
|
||||
android:id="@+id/grid"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="28dp"
|
||||
sysui:verticalSpacing="4dp"
|
||||
sysui:horizontalSpacing="4dp"
|
||||
sysui:fixedChildWidth="80dp"
|
||||
sysui:layout_constraintTop_toBottomOf="@id/title"
|
||||
sysui:layout_constraintStart_toStartOf="parent"
|
||||
sysui:layout_constraintEnd_toEndOf="parent"
|
||||
sysui:layout_constraintBottom_toTopOf="@id/barrier"
|
||||
/>
|
||||
|
||||
<androidx.constraintlayout.widget.Barrier
|
||||
android:id="@+id/barrier"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="wrap_content"
|
||||
sysui:barrierDirection="top"
|
||||
sysui:constraint_referenced_ids="settings,done"
|
||||
android:id="@+id/grid"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
sysui:verticalSpacing="20dp"
|
||||
sysui:horizontalSpacing="4dp"
|
||||
sysui:fixedChildWidth="80dp"
|
||||
/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/settings"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="48dp"
|
||||
android:text="@string/quick_settings_more_user_settings"
|
||||
sysui:layout_constraintTop_toBottomOf="@id/barrier"
|
||||
sysui:layout_constraintBottom_toBottomOf="parent"
|
||||
sysui:layout_constraintStart_toStartOf="parent"
|
||||
sysui:layout_constraintEnd_toStartOf="@id/done"
|
||||
sysui:layout_constraintHorizontal_chainStyle="spread_inside"
|
||||
style="@style/Widget.Dialog.Button.BorderButton"
|
||||
/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/done"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="48dp"
|
||||
android:text="@string/quick_settings_done"
|
||||
sysui:layout_constraintTop_toBottomOf="@id/barrier"
|
||||
sysui:layout_constraintBottom_toBottomOf="parent"
|
||||
sysui:layout_constraintStart_toEndOf="@id/settings"
|
||||
sysui:layout_constraintEnd_toEndOf="parent"
|
||||
style="@style/Widget.Dialog.Button"
|
||||
/>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</FrameLayout>
|
||||
@@ -133,10 +133,7 @@ public class PseudoGridView extends ViewGroup {
|
||||
x += width + mHorizontalSpacing;
|
||||
}
|
||||
}
|
||||
y += maxHeight;
|
||||
if (row > 0) {
|
||||
y += mVerticalSpacing;
|
||||
}
|
||||
y += maxHeight + mVerticalSpacing;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.qs.user
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.view.Gravity
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.WindowInsets
|
||||
import android.view.WindowManager
|
||||
import com.android.systemui.qs.PseudoGridView
|
||||
import com.android.systemui.statusbar.phone.SystemUIDialog
|
||||
import com.android.systemui.R
|
||||
|
||||
/**
|
||||
* Dialog for switching users or creating new ones.
|
||||
*/
|
||||
class UserDialog(
|
||||
context: Context
|
||||
) : SystemUIDialog(context) {
|
||||
|
||||
// create() is no-op after creation
|
||||
private lateinit var _doneButton: View
|
||||
/**
|
||||
* Button with text "Done" in dialog.
|
||||
*/
|
||||
val doneButton: View
|
||||
get() {
|
||||
create()
|
||||
return _doneButton
|
||||
}
|
||||
|
||||
private lateinit var _settingsButton: View
|
||||
/**
|
||||
* Button with text "User Settings" in dialog.
|
||||
*/
|
||||
val settingsButton: View
|
||||
get() {
|
||||
create()
|
||||
return _settingsButton
|
||||
}
|
||||
|
||||
private lateinit var _grid: PseudoGridView
|
||||
/**
|
||||
* Grid to populate with user avatar from adapter
|
||||
*/
|
||||
val grid: ViewGroup
|
||||
get() {
|
||||
create()
|
||||
return _grid
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
window?.apply {
|
||||
setType(WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL)
|
||||
attributes.fitInsetsTypes = attributes.fitInsetsTypes or WindowInsets.Type.statusBars()
|
||||
attributes.receiveInsetsIgnoringZOrder = true
|
||||
setGravity(Gravity.CENTER)
|
||||
}
|
||||
setContentView(R.layout.qs_user_dialog_content)
|
||||
|
||||
_doneButton = requireViewById(R.id.done)
|
||||
_settingsButton = requireViewById(R.id.settings)
|
||||
_grid = requireViewById(R.id.grid)
|
||||
}
|
||||
}
|
||||
@@ -21,13 +21,16 @@ import android.content.Context
|
||||
import android.content.DialogInterface
|
||||
import android.content.Intent
|
||||
import android.provider.Settings
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.animation.DialogLaunchAnimator
|
||||
import com.android.systemui.dagger.SysUISingleton
|
||||
import com.android.systemui.plugins.ActivityStarter
|
||||
import com.android.systemui.plugins.FalsingManager
|
||||
import com.android.systemui.qs.tiles.UserDetailView
|
||||
import com.android.systemui.statusbar.phone.SystemUIDialog
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Provider
|
||||
|
||||
@@ -40,7 +43,7 @@ class UserSwitchDialogController @VisibleForTesting constructor(
|
||||
private val activityStarter: ActivityStarter,
|
||||
private val falsingManager: FalsingManager,
|
||||
private val dialogLaunchAnimator: DialogLaunchAnimator,
|
||||
private val dialogFactory: (Context) -> UserDialog
|
||||
private val dialogFactory: (Context) -> SystemUIDialog
|
||||
) {
|
||||
|
||||
@Inject
|
||||
@@ -54,7 +57,7 @@ class UserSwitchDialogController @VisibleForTesting constructor(
|
||||
activityStarter,
|
||||
falsingManager,
|
||||
dialogLaunchAnimator,
|
||||
{ UserDialog(it) }
|
||||
{ SystemUIDialog(it) }
|
||||
)
|
||||
|
||||
companion object {
|
||||
@@ -71,9 +74,10 @@ class UserSwitchDialogController @VisibleForTesting constructor(
|
||||
with(dialogFactory(view.context)) {
|
||||
setShowForAllUsers(true)
|
||||
setCanceledOnTouchOutside(true)
|
||||
create() // Needs to be called before we can retrieve views
|
||||
|
||||
settingsButton.setOnClickListener {
|
||||
setTitle(R.string.qs_user_switch_dialog_title)
|
||||
setPositiveButton(R.string.quick_settings_done, null)
|
||||
setNeutralButton(R.string.quick_settings_more_user_settings) { _, _ ->
|
||||
if (!falsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
|
||||
dialogLaunchAnimator.disableAllCurrentDialogsExitAnimations()
|
||||
activityStarter.postStartActivityDismissingKeyguard(
|
||||
@@ -81,12 +85,14 @@ class UserSwitchDialogController @VisibleForTesting constructor(
|
||||
0
|
||||
)
|
||||
}
|
||||
dismiss()
|
||||
}
|
||||
doneButton.setOnClickListener { dismiss() }
|
||||
val gridFrame = LayoutInflater.from(this.context)
|
||||
.inflate(R.layout.qs_user_dialog_content, null)
|
||||
setView(gridFrame)
|
||||
|
||||
val adapter = userDetailViewAdapterProvider.get()
|
||||
adapter.linkToViewGroup(grid)
|
||||
|
||||
adapter.linkToViewGroup(gridFrame.findViewById(R.id.grid))
|
||||
|
||||
val hostDialog = dialogLaunchAnimator.showFromView(this, view)
|
||||
adapter.injectDialogShower(DialogShowerImpl(hostDialog, dialogLaunchAnimator))
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.qs.user
|
||||
|
||||
import android.testing.AndroidTestingRunner
|
||||
import android.testing.TestableLooper
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner::class)
|
||||
@TestableLooper.RunWithLooper
|
||||
class UserDialogTest : SysuiTestCase() {
|
||||
|
||||
private lateinit var dialog: UserDialog
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
dialog = UserDialog(mContext)
|
||||
}
|
||||
|
||||
@After
|
||||
fun tearDown() {
|
||||
dialog.dismiss()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun doneButtonExists() {
|
||||
assertThat(dialog.doneButton).isInstanceOf(View::class.java)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun settingsButtonExists() {
|
||||
assertThat(dialog.settingsButton).isInstanceOf(View::class.java)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun gridExistsAndIsViewGroup() {
|
||||
assertThat(dialog.grid).isInstanceOf(ViewGroup::class.java)
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.android.systemui.qs.user
|
||||
|
||||
import android.app.Dialog
|
||||
import android.content.DialogInterface
|
||||
import android.content.Intent
|
||||
import android.provider.Settings
|
||||
import android.testing.AndroidTestingRunner
|
||||
@@ -28,6 +29,7 @@ import com.android.systemui.plugins.ActivityStarter
|
||||
import com.android.systemui.plugins.FalsingManager
|
||||
import com.android.systemui.qs.PseudoGridView
|
||||
import com.android.systemui.qs.tiles.UserDetailView
|
||||
import com.android.systemui.statusbar.phone.SystemUIDialog
|
||||
import com.android.systemui.util.mockito.any
|
||||
import com.android.systemui.util.mockito.argumentCaptor
|
||||
import com.android.systemui.util.mockito.capture
|
||||
@@ -43,7 +45,6 @@ import org.mockito.Mockito.`when`
|
||||
import org.mockito.Mockito.anyBoolean
|
||||
import org.mockito.Mockito.anyInt
|
||||
import org.mockito.Mockito.argThat
|
||||
import org.mockito.Mockito.inOrder
|
||||
import org.mockito.Mockito.never
|
||||
import org.mockito.Mockito.verify
|
||||
import org.mockito.MockitoAnnotations
|
||||
@@ -53,27 +54,21 @@ import org.mockito.MockitoAnnotations
|
||||
class UserSwitchDialogControllerTest : SysuiTestCase() {
|
||||
|
||||
@Mock
|
||||
private lateinit var dialog: UserDialog
|
||||
private lateinit var dialog: SystemUIDialog
|
||||
@Mock
|
||||
private lateinit var falsingManager: FalsingManager
|
||||
@Mock
|
||||
private lateinit var settingsView: View
|
||||
@Mock
|
||||
private lateinit var doneView: View
|
||||
@Mock
|
||||
private lateinit var activityStarter: ActivityStarter
|
||||
@Mock
|
||||
private lateinit var userDetailViewAdapter: UserDetailView.Adapter
|
||||
@Mock
|
||||
private lateinit var launchView: View
|
||||
@Mock
|
||||
private lateinit var gridView: PseudoGridView
|
||||
@Mock
|
||||
private lateinit var dialogLaunchAnimator: DialogLaunchAnimator
|
||||
@Mock
|
||||
private lateinit var hostDialog: Dialog
|
||||
@Captor
|
||||
private lateinit var clickCaptor: ArgumentCaptor<View.OnClickListener>
|
||||
private lateinit var clickCaptor: ArgumentCaptor<DialogInterface.OnClickListener>
|
||||
|
||||
private lateinit var controller: UserSwitchDialogController
|
||||
|
||||
@@ -81,11 +76,8 @@ class UserSwitchDialogControllerTest : SysuiTestCase() {
|
||||
fun setUp() {
|
||||
MockitoAnnotations.initMocks(this)
|
||||
|
||||
`when`(dialog.settingsButton).thenReturn(settingsView)
|
||||
`when`(dialog.doneButton).thenReturn(doneView)
|
||||
`when`(dialog.grid).thenReturn(gridView)
|
||||
|
||||
`when`(launchView.context).thenReturn(mContext)
|
||||
`when`(dialog.context).thenReturn(mContext)
|
||||
`when`(dialogLaunchAnimator.showFromView(any(), any(), anyBoolean()))
|
||||
.thenReturn(hostDialog)
|
||||
|
||||
@@ -104,30 +96,6 @@ class UserSwitchDialogControllerTest : SysuiTestCase() {
|
||||
verify(dialogLaunchAnimator).showFromView(dialog, launchView)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun createCalledBeforeDoneButton() {
|
||||
controller.showDialog(launchView)
|
||||
val inOrder = inOrder(dialog)
|
||||
inOrder.verify(dialog).create()
|
||||
inOrder.verify(dialog).doneButton
|
||||
}
|
||||
|
||||
@Test
|
||||
fun createCalledBeforeSettingsButton() {
|
||||
controller.showDialog(launchView)
|
||||
val inOrder = inOrder(dialog)
|
||||
inOrder.verify(dialog).create()
|
||||
inOrder.verify(dialog).settingsButton
|
||||
}
|
||||
|
||||
@Test
|
||||
fun createCalledBeforeGrid() {
|
||||
controller.showDialog(launchView)
|
||||
val inOrder = inOrder(dialog)
|
||||
inOrder.verify(dialog).create()
|
||||
inOrder.verify(dialog).grid
|
||||
}
|
||||
|
||||
@Test
|
||||
fun dialog_showForAllUsers() {
|
||||
controller.showDialog(launchView)
|
||||
@@ -143,51 +111,44 @@ class UserSwitchDialogControllerTest : SysuiTestCase() {
|
||||
@Test
|
||||
fun adapterAndGridLinked() {
|
||||
controller.showDialog(launchView)
|
||||
verify(userDetailViewAdapter).linkToViewGroup(gridView)
|
||||
verify(userDetailViewAdapter).linkToViewGroup(any<PseudoGridView>())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun clickDoneButton_dismiss() {
|
||||
fun doneButtonSetWithNullHandler() {
|
||||
controller.showDialog(launchView)
|
||||
|
||||
verify(doneView).setOnClickListener(capture(clickCaptor))
|
||||
|
||||
clickCaptor.value.onClick(doneView)
|
||||
|
||||
verify(activityStarter, never()).postStartActivityDismissingKeyguard(any(), anyInt())
|
||||
verify(dialog).dismiss()
|
||||
verify(dialog).setPositiveButton(anyInt(), eq(null))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun clickSettingsButton_noFalsing_opensSettingsAndDismisses() {
|
||||
fun clickSettingsButton_noFalsing_opensSettings() {
|
||||
`when`(falsingManager.isFalseTap(anyInt())).thenReturn(false)
|
||||
|
||||
controller.showDialog(launchView)
|
||||
|
||||
verify(settingsView).setOnClickListener(capture(clickCaptor))
|
||||
verify(dialog).setNeutralButton(anyInt(), capture(clickCaptor))
|
||||
|
||||
clickCaptor.value.onClick(settingsView)
|
||||
clickCaptor.value.onClick(dialog, DialogInterface.BUTTON_NEUTRAL)
|
||||
|
||||
verify(activityStarter)
|
||||
.postStartActivityDismissingKeyguard(
|
||||
argThat(IntentMatcher(Settings.ACTION_USER_SETTINGS)),
|
||||
eq(0)
|
||||
)
|
||||
verify(dialog).dismiss()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun clickSettingsButton_Falsing_notOpensSettingsAndDismisses() {
|
||||
fun clickSettingsButton_Falsing_notOpensSettings() {
|
||||
`when`(falsingManager.isFalseTap(anyInt())).thenReturn(true)
|
||||
|
||||
controller.showDialog(launchView)
|
||||
|
||||
verify(settingsView).setOnClickListener(capture(clickCaptor))
|
||||
verify(dialog).setNeutralButton(anyInt(), capture(clickCaptor))
|
||||
|
||||
clickCaptor.value.onClick(settingsView)
|
||||
clickCaptor.value.onClick(dialog, DialogInterface.BUTTON_NEUTRAL)
|
||||
|
||||
verify(activityStarter, never()).postStartActivityDismissingKeyguard(any(), anyInt())
|
||||
verify(dialog).dismiss()
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user