1 /*
<lambda>null2  * Copyright 2021 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 androidx.wear.compose.material.samples
18 
19 import androidx.annotation.Sampled
20 import androidx.compose.foundation.progressSemantics
21 import androidx.compose.runtime.Composable
22 import androidx.compose.runtime.getValue
23 import androidx.compose.runtime.mutableStateOf
24 import androidx.compose.runtime.remember
25 import androidx.compose.runtime.setValue
26 import androidx.compose.ui.Modifier
27 import androidx.compose.ui.semantics.disabled
28 import androidx.compose.ui.semantics.semantics
29 import androidx.compose.ui.semantics.setProgress
30 import androidx.compose.ui.util.lerp
31 import androidx.wear.compose.material.Icon
32 import androidx.wear.compose.material.Stepper
33 import androidx.wear.compose.material.StepperDefaults
34 import androidx.wear.compose.material.Text
35 import kotlin.math.roundToInt
36 
37 @Sampled
38 @Composable
39 fun StepperSample() {
40     var value by remember { mutableStateOf(2f) }
41     Stepper(
42         value = value,
43         onValueChange = { value = it },
44         valueRange = 1f..4f,
45         increaseIcon = { Icon(StepperDefaults.Increase, "Increase") },
46         decreaseIcon = { Icon(StepperDefaults.Decrease, "Decrease") },
47         steps = 7
48     ) {
49         Text("Value: $value")
50     }
51 }
52 
53 @Sampled
54 @Composable
StepperWithIntegerSamplenull55 fun StepperWithIntegerSample() {
56     var value by remember { mutableStateOf(2) }
57     Stepper(
58         value = value,
59         onValueChange = { value = it },
60         increaseIcon = { Icon(StepperDefaults.Increase, "Increase") },
61         decreaseIcon = { Icon(StepperDefaults.Decrease, "Decrease") },
62         valueProgression = 1..10
63     ) {
64         Text("Value: $value")
65     }
66 }
67 
68 @Sampled
69 @Composable
StepperWithoutRangeSemanticsSamplenull70 fun StepperWithoutRangeSemanticsSample() {
71     var value by remember { mutableStateOf(2f) }
72     Stepper(
73         value = value,
74         onValueChange = { value = it },
75         valueRange = 1f..4f,
76         increaseIcon = { Icon(StepperDefaults.Increase, "Increase") },
77         decreaseIcon = { Icon(StepperDefaults.Decrease, "Decrease") },
78         steps = 7,
79         enableRangeSemantics = false
80     ) {
81         Text("Value: $value")
82     }
83 }
84 
85 @Sampled
86 @Composable
StepperWithCustomSemanticsSamplenull87 fun StepperWithCustomSemanticsSample() {
88     var value by remember { mutableStateOf(2f) }
89     val valueRange = 1f..4f
90     val onValueChange = { i: Float -> value = i }
91     val steps = 7
92 
93     Stepper(
94         value = value,
95         onValueChange = onValueChange,
96         valueRange = valueRange,
97         modifier = Modifier.customSemantics(value, true, onValueChange, valueRange, steps),
98         increaseIcon = { Icon(StepperDefaults.Increase, "Increase") },
99         decreaseIcon = { Icon(StepperDefaults.Decrease, "Decrease") },
100         steps = steps,
101         enableRangeSemantics = false
102     ) {
103         Text("Value: $value")
104     }
105 }
106 
107 // Declaring the custom semantics for StepperWithCustomSemanticsSample
customSemanticsnull108 private fun Modifier.customSemantics(
109     value: Float,
110     enabled: Boolean,
111     onValueChange: (Float) -> Unit,
112     valueRange: ClosedFloatingPointRange<Float>,
113     steps: Int
114 ): Modifier =
115     semantics(mergeDescendants = true) {
116             if (!enabled) disabled()
117             setProgress(
118                 action = { targetValue ->
119                     val newStepIndex =
120                         ((value - valueRange.start) / (valueRange.endInclusive - valueRange.start) *
121                                 (steps + 1))
122                             .roundToInt()
123                             .coerceIn(0, steps + 1)
124 
125                     if (value.toInt() == newStepIndex) {
126                         false
127                     } else {
128                         onValueChange(targetValue)
129                         true
130                     }
131                 }
132             )
133         }
134         .progressSemantics(
135             lerp(valueRange.start, valueRange.endInclusive, value / (steps + 1).toFloat())
136                 .coerceIn(valueRange),
137             valueRange,
138             steps
139         )
140