• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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