1 /*
<lambda>null2 * Copyright 2023 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.compose.animation.scene.demo
18
19 import androidx.compose.foundation.background
20 import androidx.compose.foundation.layout.Box
21 import androidx.compose.foundation.layout.fillMaxSize
22 import androidx.compose.foundation.layout.padding
23 import androidx.compose.foundation.layout.size
24 import androidx.compose.foundation.overscroll
25 import androidx.compose.foundation.shape.CircleShape
26 import androidx.compose.material.icons.Icons
27 import androidx.compose.material.icons.filled.ArrowBack
28 import androidx.compose.material.icons.filled.Check
29 import androidx.compose.material3.Button
30 import androidx.compose.material3.ButtonDefaults
31 import androidx.compose.material3.Icon
32 import androidx.compose.material3.MaterialTheme
33 import androidx.compose.runtime.Composable
34 import androidx.compose.ui.Alignment
35 import androidx.compose.ui.Modifier
36 import androidx.compose.ui.graphics.vector.ImageVector
37 import androidx.compose.ui.unit.dp
38 import com.android.compose.animation.scene.Back
39 import com.android.compose.animation.scene.ContentScope
40 import com.android.compose.animation.scene.ElementKey
41 import com.android.compose.animation.scene.SceneKey
42 import com.android.compose.animation.scene.Swipe
43 import com.android.compose.grid.VerticalGrid
44
45 object Bouncer {
46 fun userActions(lockscreenScene: SceneKey) =
47 mapOf(Back to lockscreenScene, Swipe.Down to lockscreenScene)
48
49 object Elements {
50 val Background = ElementKey("BouncerBackground")
51 val Content = ElementKey("BouncerContent")
52 }
53 }
54
55 @Composable
Bouncernull56 fun ContentScope.Bouncer(
57 onBouncerCancelled: () -> Unit,
58 onBouncerSolved: () -> Unit,
59 modifier: Modifier = Modifier,
60 ) {
61 Box(modifier) {
62 Box(
63 Modifier.element(Bouncer.Elements.Background)
64 .fillMaxSize()
65 .background(MaterialTheme.colorScheme.surfaceContainer)
66 )
67
68 val nColumns = 3
69 val nRows = 4
70 val gridSpacing = 24.dp
71 val normalButtonColor = MaterialTheme.colorScheme.surfaceBright
72 val actionButtonColor = MaterialTheme.colorScheme.tertiary
73 val actionIconColor = MaterialTheme.colorScheme.onTertiary
74
75 VerticalGrid(
76 columns = 3,
77 Modifier.overscroll(verticalOverscrollEffect)
78 .align(Alignment.BottomCenter)
79 .padding(bottom = 100.dp)
80 .element(Bouncer.Elements.Content),
81 horizontalSpacing = gridSpacing,
82 verticalSpacing = gridSpacing,
83 ) {
84 repeat(nRows * nColumns) { i ->
85 val row = i / nColumns
86 val col = i % nColumns
87
88 val isLastRow = row == nRows - 1
89 val isFirstColumn = col == 0
90 val isLastColumn = col == nColumns - 1
91 val isCancelButton = isLastRow && isFirstColumn
92 val isSolveButton = isLastRow && isLastColumn
93
94 val color =
95 if (isCancelButton || isSolveButton) {
96 actionButtonColor
97 } else {
98 normalButtonColor
99 }
100
101 Button(
102 onClick = {
103 when {
104 isCancelButton -> onBouncerCancelled()
105 isSolveButton -> onBouncerSolved()
106 }
107 },
108 modifier = Modifier.size(80.dp),
109 colors = ButtonDefaults.buttonColors(containerColor = color),
110 shape = CircleShape,
111 elevation = null,
112 ) {
113 val icon: ImageVector? =
114 when {
115 isCancelButton -> Icons.Default.ArrowBack
116 isSolveButton -> Icons.Default.Check
117 else -> null
118 }
119
120 icon?.let { Icon(it, null, tint = actionIconColor) }
121 }
122 }
123 }
124 }
125 }
126