diff options
| author | 2024-01-24 23:07:48 +0000 | |
|---|---|---|
| committer | 2024-01-24 23:07:48 +0000 | |
| commit | 8790c0824d1a33f719787215d39d939d29999978 (patch) | |
| tree | 29188122042c52acedd437ab9fb33b21a062ef36 | |
| parent | 1ca908dc27e4781e23b6da35d4a1b8db55a5df4e (diff) | |
| parent | 10a22e2a9cea6b55d74b972e5d704dbd45fc2bd2 (diff) | |
Merge "Add splitshade blueprint in compose." into main
3 files changed, 216 insertions, 16 deletions
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/DefaultBlueprint.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/DefaultBlueprint.kt index 56d6879e614e..bf02d8abf73c 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/DefaultBlueprint.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/DefaultBlueprint.kt @@ -173,7 +173,8 @@ constructor( val belowLockIconPlaceable = belowLockIconMeasurable.measure( noMinConstraints.copy( - maxHeight = constraints.maxHeight - lockIconBounds.bottom + maxHeight = + (constraints.maxHeight - lockIconBounds.bottom).coerceAtLeast(0) ) ) val startShortcutPleaceable = startShortcutMeasurable.measure(noMinConstraints) diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/SplitShadeBlueprint.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/SplitShadeBlueprint.kt index fdf11668ae76..616a7b4752a0 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/SplitShadeBlueprint.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/SplitShadeBlueprint.kt @@ -16,19 +16,42 @@ package com.android.systemui.keyguard.ui.composable.blueprint -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Box -import androidx.compose.material3.Text +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color +import androidx.compose.ui.layout.Layout +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.dimensionResource +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.IntRect +import androidx.compose.ui.unit.dp import com.android.compose.animation.scene.SceneScope +import com.android.compose.modifiers.padding +import com.android.systemui.Flags +import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor import com.android.systemui.keyguard.ui.composable.LockscreenLongPress +import com.android.systemui.keyguard.ui.composable.section.AmbientIndicationSection +import com.android.systemui.keyguard.ui.composable.section.BottomAreaSection +import com.android.systemui.keyguard.ui.composable.section.ClockSection +import com.android.systemui.keyguard.ui.composable.section.LockSection +import com.android.systemui.keyguard.ui.composable.section.NotificationSection +import com.android.systemui.keyguard.ui.composable.section.SettingsMenuSection +import com.android.systemui.keyguard.ui.composable.section.SmartSpaceSection +import com.android.systemui.keyguard.ui.composable.section.StatusBarSection import com.android.systemui.keyguard.ui.viewmodel.LockscreenContentViewModel +import com.android.systemui.res.R +import com.android.systemui.shade.LargeScreenHeaderHelper import dagger.Binds import dagger.Module import dagger.multibindings.IntoSet +import java.util.Optional import javax.inject.Inject /** @@ -39,22 +62,174 @@ class SplitShadeBlueprint @Inject constructor( private val viewModel: LockscreenContentViewModel, + private val statusBarSection: StatusBarSection, + private val clockSection: ClockSection, + private val smartSpaceSection: SmartSpaceSection, + private val notificationSection: NotificationSection, + private val lockSection: LockSection, + private val ambientIndicationSectionOptional: Optional<AmbientIndicationSection>, + private val bottomAreaSection: BottomAreaSection, + private val settingsMenuSection: SettingsMenuSection, + private val clockInteractor: KeyguardClockInteractor, + private val largeScreenHeaderHelper: LargeScreenHeaderHelper, ) : LockscreenSceneBlueprint { override val id: String = "split-shade" @Composable override fun SceneScope.Content(modifier: Modifier) { + val isUdfpsVisible = viewModel.isUdfpsVisible + val burnIn = rememberBurnIn(clockInteractor) + val resources = LocalContext.current.resources + LockscreenLongPress( viewModel = viewModel.longPress, modifier = modifier, - ) { _ -> - Box(modifier.background(Color.Black)) { - Text( - text = "TODO(b/316211368): split shade blueprint", - color = Color.White, - modifier = Modifier.align(Alignment.Center), - ) + ) { onSettingsMenuPlaced -> + Layout( + content = { + // Constrained to above the lock icon. + Column( + modifier = Modifier.fillMaxSize(), + ) { + with(statusBarSection) { StatusBar(modifier = Modifier.fillMaxWidth()) } + Row( + modifier = Modifier.fillMaxSize(), + ) { + Column( + modifier = Modifier.fillMaxHeight().weight(weight = 1f), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + with(smartSpaceSection) { + SmartSpace( + burnInParams = burnIn.parameters, + onTopChanged = burnIn.onSmartspaceTopChanged, + modifier = + Modifier.fillMaxWidth() + .padding( + top = { + viewModel.getSmartSpacePaddingTop(resources) + } + ), + ) + } + + Spacer(modifier = Modifier.weight(weight = 1f)) + with(clockSection) { LargeClock() } + Spacer(modifier = Modifier.weight(weight = 1f)) + } + with(notificationSection) { + val splitShadeTopMargin: Dp = + if (Flags.centralizedStatusBarDimensRefactor()) { + largeScreenHeaderHelper.getLargeScreenHeaderHeight().dp + } else { + dimensionResource( + id = R.dimen.large_screen_shade_header_height + ) + } + Notifications( + modifier = + Modifier.fillMaxHeight() + .weight(weight = 1f) + .padding(top = splitShadeTopMargin) + ) + } + } + + if (!isUdfpsVisible && ambientIndicationSectionOptional.isPresent) { + with(ambientIndicationSectionOptional.get()) { + AmbientIndication(modifier = Modifier.fillMaxWidth()) + } + } + } + + with(lockSection) { LockIcon() } + + // Aligned to bottom and constrained to below the lock icon. + Column(modifier = Modifier.fillMaxWidth()) { + if (isUdfpsVisible && ambientIndicationSectionOptional.isPresent) { + with(ambientIndicationSectionOptional.get()) { + AmbientIndication(modifier = Modifier.fillMaxWidth()) + } + } + + with(bottomAreaSection) { + IndicationArea(modifier = Modifier.fillMaxWidth()) + } + } + + // Aligned to bottom and NOT constrained by the lock icon. + with(bottomAreaSection) { + Shortcut(isStart = true, applyPadding = true) + Shortcut(isStart = false, applyPadding = true) + } + with(settingsMenuSection) { SettingsMenu(onSettingsMenuPlaced) } + }, + modifier = Modifier.fillMaxSize(), + ) { measurables, constraints -> + check(measurables.size == 6) + val aboveLockIconMeasurable = measurables[0] + val lockIconMeasurable = measurables[1] + val belowLockIconMeasurable = measurables[2] + val startShortcutMeasurable = measurables[3] + val endShortcutMeasurable = measurables[4] + val settingsMenuMeasurable = measurables[5] + + val noMinConstraints = + constraints.copy( + minWidth = 0, + minHeight = 0, + ) + val lockIconPlaceable = lockIconMeasurable.measure(noMinConstraints) + val lockIconBounds = + IntRect( + left = lockIconPlaceable[BlueprintAlignmentLines.LockIcon.Left], + top = lockIconPlaceable[BlueprintAlignmentLines.LockIcon.Top], + right = lockIconPlaceable[BlueprintAlignmentLines.LockIcon.Right], + bottom = lockIconPlaceable[BlueprintAlignmentLines.LockIcon.Bottom], + ) + + val aboveLockIconPlaceable = + aboveLockIconMeasurable.measure( + noMinConstraints.copy(maxHeight = lockIconBounds.top) + ) + val belowLockIconPlaceable = + belowLockIconMeasurable.measure( + noMinConstraints.copy( + maxHeight = + (constraints.maxHeight - lockIconBounds.bottom).coerceAtLeast(0) + ) + ) + val startShortcutPleaceable = startShortcutMeasurable.measure(noMinConstraints) + val endShortcutPleaceable = endShortcutMeasurable.measure(noMinConstraints) + val settingsMenuPlaceable = settingsMenuMeasurable.measure(noMinConstraints) + + layout(constraints.maxWidth, constraints.maxHeight) { + aboveLockIconPlaceable.place( + x = 0, + y = 0, + ) + lockIconPlaceable.place( + x = lockIconBounds.left, + y = lockIconBounds.top, + ) + belowLockIconPlaceable.place( + x = 0, + y = constraints.maxHeight - belowLockIconPlaceable.height, + ) + startShortcutPleaceable.place( + x = 0, + y = constraints.maxHeight - startShortcutPleaceable.height, + ) + endShortcutPleaceable.place( + x = constraints.maxWidth - endShortcutPleaceable.width, + y = constraints.maxHeight - endShortcutPleaceable.height, + ) + settingsMenuPlaceable.place( + x = (constraints.maxWidth - settingsMenuPlaceable.width) / 2, + y = constraints.maxHeight - settingsMenuPlaceable.height, + ) + } } } } diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/ClockSection.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/ClockSection.kt index f40b871e923c..8f218792ee32 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/ClockSection.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/ClockSection.kt @@ -16,7 +16,8 @@ package com.android.systemui.keyguard.ui.composable.section -import androidx.compose.foundation.layout.fillMaxWidth +import android.view.ViewGroup +import android.widget.FrameLayout import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect @@ -75,7 +76,13 @@ constructor( ) { content { AndroidView( - factory = { checkNotNull(currentClock).smallClock.view }, + factory = { context -> + FrameLayout(context).apply { + val newClockView = checkNotNull(currentClock).smallClock.view + (newClockView.parent as? ViewGroup)?.removeView(newClockView) + addView(newClockView) + } + }, modifier = Modifier.padding( horizontal = @@ -83,6 +90,12 @@ constructor( ) .padding(top = { viewModel.getSmallClockTopMargin(view.context) }) .onTopPlacementChanged(onTopChanged), + update = { + val newClockView = checkNotNull(currentClock).smallClock.view + it.removeAllViews() + (newClockView.parent as? ViewGroup)?.removeView(newClockView) + it.addView(newClockView) + }, ) } } @@ -116,8 +129,19 @@ constructor( ) { content { AndroidView( - factory = { checkNotNull(currentClock).largeClock.view }, - modifier = Modifier.fillMaxWidth() + factory = { context -> + FrameLayout(context).apply { + val newClockView = checkNotNull(currentClock).largeClock.view + (newClockView.parent as? ViewGroup)?.removeView(newClockView) + addView(newClockView) + } + }, + update = { + val newClockView = checkNotNull(currentClock).largeClock.view + it.removeAllViews() + (newClockView.parent as? ViewGroup)?.removeView(newClockView) + it.addView(newClockView) + }, ) } } |