diff options
author | 2024-09-18 15:51:14 +0000 | |
---|---|---|
committer | 2024-09-19 16:53:54 +0000 | |
commit | c07e6f8ed283a44ac540bd182ad688079458b469 (patch) | |
tree | 48a8310e650b546a4d23948eb2ccce67e28b9887 /packages | |
parent | 3d404328e80d703407a8b2393c9d254e50eb742a (diff) |
Migrated shortcut helper bottom sheet to compose
go/shortcut-helper-bottom-sheet-compose-migration
Test: None
Flag: com.android.systemui.keyboard_shortcut_helper_rewrite
Fixes: 366152089
Fix: 362733881
Fix: 355153229
Fix: 362730283
Fix: 362740106
Fix: 362735926
Fix: 362732358
Change-Id: I47d25c9288a7243997d60c353241914fff75073b
Diffstat (limited to 'packages')
8 files changed, 127 insertions, 170 deletions
diff --git a/packages/SystemUI/res-keyguard/values-sw600dp/dimens.xml b/packages/SystemUI/res-keyguard/values-sw600dp/dimens.xml index 84f7a5133593..6c8db91d49bb 100644 --- a/packages/SystemUI/res-keyguard/values-sw600dp/dimens.xml +++ b/packages/SystemUI/res-keyguard/values-sw600dp/dimens.xml @@ -28,8 +28,4 @@ <!-- Overload default clock widget parameters --> <dimen name="widget_big_font_size">100dp</dimen> <dimen name="widget_label_font_size">18sp</dimen> - - <!-- New keyboard shortcut helper --> - <dimen name="shortcut_helper_width">704dp</dimen> - <dimen name="shortcut_helper_height">1208dp</dimen> </resources> diff --git a/packages/SystemUI/res/layout/activity_keyboard_shortcut_helper.xml b/packages/SystemUI/res/layout/activity_keyboard_shortcut_helper.xml deleted file mode 100644 index a15532f7aed2..000000000000 --- a/packages/SystemUI/res/layout/activity_keyboard_shortcut_helper.xml +++ /dev/null @@ -1,28 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:app="http://schemas.android.com/apk/res-auto" - android:id="@+id/shortcut_helper_sheet_container" - android:layout_gravity="center_horizontal|bottom" - android:layout_width="match_parent" - android:layout_height="match_parent"> - - <FrameLayout - android:id="@+id/shortcut_helper_sheet" - style="@style/ShortcutHelperBottomSheet" - android:layout_width="@dimen/shortcut_helper_width" - android:layout_height="@dimen/shortcut_helper_height" - android:orientation="vertical" - app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior"> - - <!-- Drag handle for accessibility --> - <com.google.android.material.bottomsheet.BottomSheetDragHandleView - android:id="@+id/drag_handle" - android:layout_width="match_parent" - android:layout_height="wrap_content" /> - - <androidx.compose.ui.platform.ComposeView - android:id="@+id/shortcut_helper_compose_container" - android:layout_width="match_parent" - android:layout_height="match_parent" /> - </FrameLayout> -</androidx.coordinatorlayout.widget.CoordinatorLayout>
\ No newline at end of file diff --git a/packages/SystemUI/res/values-sw600dp-land/dimens.xml b/packages/SystemUI/res/values-sw600dp-land/dimens.xml index 3efe7a560d94..2a27b47e54ca 100644 --- a/packages/SystemUI/res/values-sw600dp-land/dimens.xml +++ b/packages/SystemUI/res/values-sw600dp-land/dimens.xml @@ -26,10 +26,6 @@ <dimen name="keyguard_clock_top_margin">8dp</dimen> <dimen name="keyguard_smartspace_top_offset">0dp</dimen> - <!-- New keyboard shortcut helper --> - <dimen name="shortcut_helper_width">864dp</dimen> - <dimen name="shortcut_helper_height">728dp</dimen> - <!-- QS--> <dimen name="qs_panel_padding_top">16dp</dimen> <dimen name="qs_panel_padding">24dp</dimen> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 00846cb10378..e94248dc72ce 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -1005,10 +1005,6 @@ <dimen name="ksh_app_item_minimum_height">64dp</dimen> <dimen name="ksh_category_separator_margin">16dp</dimen> - <!-- New keyboard shortcut helper --> - <dimen name="shortcut_helper_width">412dp</dimen> - <dimen name="shortcut_helper_height">728dp</dimen> - <!-- The size of corner radius of the arrow in the onboarding toast. --> <dimen name="recents_onboarding_toast_arrow_corner_radius">2dp</dimen> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index ba3822bd3c23..a3db7761f59d 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -3711,6 +3711,12 @@ [CHAR LIMIT=NONE] --> <string name="shortcut_helper_key_combinations_or_separator">or</string> + <!-- Content description of the drag handle that allows to swipe to dismiss the shortcut helper. + The helper is a component that shows the user which keyboard shortcuts they can + use. The helper shows shortcuts in categories, which can be collapsed or expanded. + [CHAR LIMIT=NONE] --> + <string name="shortcut_helper_content_description_drag_handle">Drag handle</string> + <!-- Keyboard touchpad tutorial scheduler--> <!-- Notification title for launching keyboard tutorial [CHAR_LIMIT=100] --> diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutHelper.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutHelper.kt index 4bf552e0f1e3..93cd1cf487b0 100644 --- a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutHelper.kt +++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutHelper.kt @@ -36,6 +36,7 @@ import androidx.compose.foundation.layout.FlowRow import androidx.compose.foundation.layout.FlowRowScope import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth @@ -71,8 +72,6 @@ import androidx.compose.material3.SearchBarDefaults import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.material3.TopAppBarDefaults -import androidx.compose.material3.windowsizeclass.WindowHeightSizeClass -import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue @@ -116,7 +115,6 @@ import androidx.compose.ui.util.fastForEach import androidx.compose.ui.util.fastForEachIndexed import androidx.compose.ui.zIndex import com.android.compose.ui.graphics.painter.rememberDrawablePainter -import com.android.compose.windowsizeclass.LocalWindowSizeClass import com.android.systemui.keyboard.shortcut.shared.model.Shortcut import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategory import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategoryType @@ -188,10 +186,7 @@ private fun ActiveShortcutHelper( } } -@Composable -private fun shouldUseSinglePane() = - LocalWindowSizeClass.current.widthSizeClass == WindowWidthSizeClass.Compact || - LocalWindowSizeClass.current.heightSizeClass == WindowHeightSizeClass.Compact +@Composable private fun shouldUseSinglePane() = hasCompactWindowSize() @Composable private fun ShortcutHelperSinglePane( @@ -425,7 +420,7 @@ private fun ShortcutHelperTwoPane( onKeyboardSettingsClicked: () -> Unit, ) { val selectedCategory = categories.fastFirstOrNull { it.type == selectedCategoryType } - Column(modifier = modifier.fillMaxSize().padding(start = 24.dp, end = 24.dp, top = 26.dp)) { + Column(modifier = modifier.fillMaxSize().padding(horizontal = 24.dp)) { TitleBar() Spacer(modifier = Modifier.height(12.dp)) Row(Modifier.fillMaxWidth()) { @@ -801,6 +796,8 @@ private fun TitleBar() { style = MaterialTheme.typography.headlineSmall, ) }, + windowInsets = WindowInsets(top = 0.dp, bottom = 0.dp, left = 0.dp, right = 0.dp), + expandedHeight = 64.dp, ) } @@ -835,6 +832,7 @@ private fun ShortcutsSearchBar(onQueryChange: (String) -> Unit) { onSearch = {}, leadingIcon = { Icon(Icons.Default.Search, contentDescription = null) }, placeholder = { Text(text = stringResource(R.string.shortcut_helper_search_placeholder)) }, + windowInsets = WindowInsets(top = 0.dp, bottom = 0.dp, left = 0.dp, right = 0.dp), content = {}, ) } @@ -847,9 +845,7 @@ private fun KeyboardSettings(horizontalPadding: Dp, verticalPadding: Dp, onClick shape = RoundedCornerShape(24.dp), color = Color.Transparent, modifier = - Modifier.semantics { role = Role.Button } - .fillMaxWidth() - .padding(horizontal = 12.dp), + Modifier.semantics { role = Role.Button }.fillMaxWidth().padding(horizontal = 12.dp), interactionSource = interactionSource, interactionsConfig = InteractionsConfig( diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutHelperUtils.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutHelperUtils.kt new file mode 100644 index 000000000000..1f0d696eebd6 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutHelperUtils.kt @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2024 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.keyboard.shortcut.ui.composable + +import androidx.compose.material3.windowsizeclass.WindowHeightSizeClass +import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass +import androidx.compose.runtime.Composable +import com.android.compose.windowsizeclass.LocalWindowSizeClass + +/** + * returns true if either size of the window is compact. This represents majority of phone windows + * portrait + */ +@Composable +fun hasCompactWindowSize() = + LocalWindowSizeClass.current.widthSizeClass == WindowWidthSizeClass.Compact || + LocalWindowSizeClass.current.heightSizeClass == WindowHeightSizeClass.Compact diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/view/ShortcutHelperActivity.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/view/ShortcutHelperActivity.kt index 799999aff29b..b9a16c402e59 100644 --- a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/view/ShortcutHelperActivity.kt +++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/view/ShortcutHelperActivity.kt @@ -18,31 +18,43 @@ package com.android.systemui.keyboard.shortcut.ui.view import android.content.ActivityNotFoundException import android.content.Intent -import android.graphics.Insets +import android.content.res.Configuration import android.os.Bundle import android.provider.Settings -import android.view.View -import android.view.WindowInsets -import androidx.activity.BackEventCompat import androidx.activity.ComponentActivity -import androidx.activity.OnBackPressedCallback +import androidx.activity.compose.setContent +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.ModalBottomSheet +import androidx.compose.material3.Surface +import androidx.compose.material3.rememberModalBottomSheetState +import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.getValue -import androidx.compose.ui.platform.ComposeView +import androidx.compose.ui.Modifier +import androidx.compose.ui.input.key.Key +import androidx.compose.ui.input.key.key +import androidx.compose.ui.input.key.onKeyEvent +import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalContext -import androidx.core.view.updatePadding +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.contentDescription +import androidx.compose.ui.semantics.semantics +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.flowWithLifecycle import androidx.lifecycle.lifecycleScope import com.android.compose.theme.PlatformTheme import com.android.systemui.keyboard.shortcut.ui.composable.ShortcutHelper +import com.android.systemui.keyboard.shortcut.ui.composable.hasCompactWindowSize import com.android.systemui.keyboard.shortcut.ui.viewmodel.ShortcutHelperViewModel import com.android.systemui.res.R import com.android.systemui.settings.UserTracker -import com.android.systemui.util.dpToPx -import com.google.android.material.bottomsheet.BottomSheetBehavior -import com.google.android.material.bottomsheet.BottomSheetBehavior.BottomSheetCallback -import com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_HIDDEN import javax.inject.Inject import kotlinx.coroutines.launch @@ -55,52 +67,58 @@ class ShortcutHelperActivity constructor(private val userTracker: UserTracker, private val viewModel: ShortcutHelperViewModel) : ComponentActivity() { - private val bottomSheetContainer - get() = requireViewById<View>(R.id.shortcut_helper_sheet_container) - - private val bottomSheet - get() = requireViewById<View>(R.id.shortcut_helper_sheet) - - private val bottomSheetBehavior - get() = BottomSheetBehavior.from(bottomSheet) - override fun onCreate(savedInstanceState: Bundle?) { setupEdgeToEdge() super.onCreate(savedInstanceState) - setContentView(R.layout.activity_keyboard_shortcut_helper) - setUpWidth() - expandBottomSheet() - setUpInsets() - setUpPredictiveBack() - setUpSheetDismissListener() - setUpDismissOnTouchOutside() - setUpComposeView() + setContent { Content() } observeFinishRequired() viewModel.onViewOpened() } - private fun setUpWidth() { - // we override this because when maxWidth isn't specified, material imposes a max width - // constraint on bottom sheets on larger screens which is smaller than our desired width. - bottomSheetBehavior.maxWidth = - resources.getDimension(R.dimen.shortcut_helper_width).dpToPx(resources).toInt() + @Composable + private fun Content() { + CompositionLocalProvider(LocalContext provides userTracker.userContext) { + PlatformTheme { BottomSheet { finish() } } + } } - private fun setUpComposeView() { - requireViewById<ComposeView>(R.id.shortcut_helper_compose_container).apply { - setContent { - CompositionLocalProvider(LocalContext provides userTracker.userContext) { - PlatformTheme { - val shortcutsUiState by - viewModel.shortcutsUiState.collectAsStateWithLifecycle() - ShortcutHelper( - shortcutsUiState = shortcutsUiState, - onKeyboardSettingsClicked = ::onKeyboardSettingsClicked, - onSearchQueryChanged = { viewModel.onSearchQueryChanged(it) }, - ) - } - } - } + @OptIn(ExperimentalMaterial3Api::class) + @Composable + private fun BottomSheet(onDismiss: () -> Unit) { + ModalBottomSheet( + onDismissRequest = { onDismiss() }, + modifier = + Modifier.width(getWidth()).padding(top = getTopPadding()).onKeyEvent { + if (it.key == Key.Escape) { + onDismiss() + true + } else false + }, + sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true), + dragHandle = { DragHandle() }, + ) { + val shortcutsUiState by viewModel.shortcutsUiState.collectAsStateWithLifecycle() + ShortcutHelper( + shortcutsUiState = shortcutsUiState, + onKeyboardSettingsClicked = ::onKeyboardSettingsClicked, + onSearchQueryChanged = { viewModel.onSearchQueryChanged(it) }, + ) + } + } + + @Composable + fun DragHandle() { + val dragHandleContentDescription = + stringResource(id = R.string.shortcut_helper_content_description_drag_handle) + Surface( + modifier = + Modifier.padding(top = 16.dp, bottom = 6.dp).semantics { + contentDescription = dragHandleContentDescription + }, + color = MaterialTheme.colorScheme.outlineVariant, + shape = MaterialTheme.shapes.extraLarge, + ) { + Box(Modifier.size(width = 32.dp, height = 4.dp)) } } @@ -139,81 +157,27 @@ constructor(private val userTracker: UserTracker, private val viewModel: Shortcu window.setDecorFitsSystemWindows(false) } - private fun setUpInsets() { - bottomSheetContainer.setOnApplyWindowInsetsListener { _, insets -> - val safeDrawingInsets = insets.safeDrawing - // Make sure the bottom sheet is not covered by the status bar. - bottomSheetBehavior.maxHeight = - windowManager.maximumWindowMetrics.bounds.height() - safeDrawingInsets.top - // Make sure the contents inside of the bottom sheet are not hidden by system bars, or - // cutouts. - bottomSheet.updatePadding( - left = safeDrawingInsets.left, - right = safeDrawingInsets.right, - bottom = safeDrawingInsets.bottom, - ) - // The bottom sheet has to be expanded only after setting up insets, otherwise there is - // a bug and it will not use full height. - expandBottomSheet() - - // Return CONSUMED if you don't want want the window insets to keep passing - // down to descendant views. - WindowInsets.CONSUMED - } - } - - private fun expandBottomSheet() { - bottomSheetBehavior.state = BottomSheetBehavior.STATE_EXPANDED - bottomSheetBehavior.skipCollapsed = true + @Composable + private fun getTopPadding(): Dp { + return if (hasCompactWindowSize()) DefaultTopPadding else LargeScreenTopPadding } - private fun setUpPredictiveBack() { - val onBackPressedCallback = - object : OnBackPressedCallback(/* enabled= */ true) { - override fun handleOnBackStarted(backEvent: BackEventCompat) { - bottomSheetBehavior.startBackProgress(backEvent) - } - - override fun handleOnBackProgressed(backEvent: BackEventCompat) { - bottomSheetBehavior.updateBackProgress(backEvent) - } - - override fun handleOnBackPressed() { - bottomSheetBehavior.handleBackInvoked() - } - - override fun handleOnBackCancelled() { - bottomSheetBehavior.cancelBackProgress() - } + @Composable + private fun getWidth(): Dp { + return if (hasCompactWindowSize()) { + DefaultWidth + } else + when (LocalConfiguration.current.orientation) { + Configuration.ORIENTATION_LANDSCAPE -> LargeScreenWidthLandscape + else -> LargeScreenWidthPortrait } - onBackPressedDispatcher.addCallback( - owner = this, - onBackPressedCallback = onBackPressedCallback, - ) } - private fun setUpSheetDismissListener() { - bottomSheetBehavior.addBottomSheetCallback( - object : BottomSheetCallback() { - override fun onStateChanged(bottomSheet: View, newState: Int) { - if (newState == STATE_HIDDEN) { - finish() - } - } - - override fun onSlide(bottomSheet: View, slideOffset: Float) {} - } - ) - } - - private fun setUpDismissOnTouchOutside() { - bottomSheetContainer.setOnClickListener { finish() } + companion object { + private val DefaultTopPadding = 64.dp + private val LargeScreenTopPadding = 72.dp + private val DefaultWidth = 412.dp + private val LargeScreenWidthPortrait = 704.dp + private val LargeScreenWidthLandscape = 864.dp } } - -private val WindowInsets.safeDrawing - get() = - getInsets(WindowInsets.Type.systemBars()) - .union(getInsets(WindowInsets.Type.displayCutout())) - -private fun Insets.union(insets: Insets): Insets = Insets.max(this, insets) |