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 android.view.MotionEvent
20 import androidx.annotation.Sampled
21 import androidx.compose.foundation.layout.Arrangement
22 import androidx.compose.foundation.layout.Box
23 import androidx.compose.foundation.layout.Row
24 import androidx.compose.foundation.layout.Spacer
25 import androidx.compose.foundation.layout.fillMaxSize
26 import androidx.compose.foundation.layout.padding
27 import androidx.compose.foundation.layout.size
28 import androidx.compose.foundation.layout.width
29 import androidx.compose.foundation.layout.wrapContentSize
30 import androidx.compose.runtime.Composable
31 import androidx.compose.runtime.derivedStateOf
32 import androidx.compose.runtime.getValue
33 import androidx.compose.runtime.mutableStateOf
34 import androidx.compose.runtime.remember
35 import androidx.compose.runtime.rememberCoroutineScope
36 import androidx.compose.runtime.setValue
37 import androidx.compose.ui.Alignment
38 import androidx.compose.ui.ExperimentalComposeUiApi
39 import androidx.compose.ui.Modifier
40 import androidx.compose.ui.input.pointer.pointerInteropFilter
41 import androidx.compose.ui.unit.dp
42 import androidx.wear.compose.material.Chip
43 import androidx.wear.compose.material.MaterialTheme
44 import androidx.wear.compose.material.Picker
45 import androidx.wear.compose.material.Text
46 import androidx.wear.compose.material.rememberPickerState
47 import kotlinx.coroutines.launch
48
49 @Sampled
50 @Composable
51 fun SimplePicker() {
52 val items = listOf("One", "Two", "Three", "Four", "Five")
53 val state = rememberPickerState(items.size)
54 val contentDescription by remember { derivedStateOf { "${state.selectedOption + 1}" } }
55 Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
56 Text(
57 modifier = Modifier.align(Alignment.TopCenter).padding(top = 10.dp),
58 text = "Selected: ${items[state.selectedOption]}"
59 )
60 Picker(
61 modifier = Modifier.size(100.dp, 100.dp),
62 state = state,
63 contentDescription = contentDescription,
64 ) {
65 Text(items[it])
66 }
67 }
68 }
69
70 @Sampled
71 @Composable
OptionChangePickernull72 fun OptionChangePicker() {
73 val coroutineScope = rememberCoroutineScope()
74 val state = rememberPickerState(initialNumberOfOptions = 10)
75 val contentDescription by remember { derivedStateOf { "${state.selectedOption + 1}" } }
76 Picker(
77 state = state,
78 separation = 4.dp,
79 contentDescription = contentDescription,
80 ) {
81 Chip(
82 onClick = { coroutineScope.launch { state.scrollToOption(it) } },
83 label = { Text("$it") }
84 )
85 }
86 }
87
88 @Sampled
89 @Composable
AnimateOptionChangePickernull90 fun AnimateOptionChangePicker() {
91 val coroutineScope = rememberCoroutineScope()
92 val state = rememberPickerState(initialNumberOfOptions = 10)
93 val contentDescription by remember { derivedStateOf { "${state.selectedOption + 1}" } }
94
95 Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
96 Picker(
97 state = state,
98 separation = 4.dp,
99 contentDescription = contentDescription,
100 ) {
101 Chip(
102 onClick = { coroutineScope.launch { state.animateScrollToOption(it) } },
103 label = { Text("$it") }
104 )
105 }
106 }
107 }
108
109 @OptIn(ExperimentalComposeUiApi::class)
110 @Sampled
111 @Composable
DualPickernull112 fun DualPicker() {
113 var selectedColumn by remember { mutableStateOf(0) }
114 val textStyle = MaterialTheme.typography.display1
115
116 @Composable
117 fun Option(column: Int, text: String) =
118 Box(modifier = Modifier.fillMaxSize()) {
119 Text(
120 text = text,
121 style = textStyle,
122 color =
123 if (selectedColumn == column) MaterialTheme.colors.secondary
124 else MaterialTheme.colors.onBackground,
125 modifier =
126 Modifier.align(Alignment.Center).wrapContentSize().pointerInteropFilter {
127 if (it.action == MotionEvent.ACTION_DOWN) selectedColumn = column
128 true
129 }
130 )
131 }
132
133 Row(
134 modifier = Modifier.fillMaxSize(),
135 verticalAlignment = Alignment.CenterVertically,
136 horizontalArrangement = Arrangement.Center,
137 ) {
138 val hourState =
139 rememberPickerState(initialNumberOfOptions = 12, initiallySelectedOption = 5)
140 val hourContentDescription by remember {
141 derivedStateOf { "${hourState.selectedOption + 1 } hours" }
142 }
143 Picker(
144 readOnly = selectedColumn != 0,
145 state = hourState,
146 modifier = Modifier.size(64.dp, 100.dp),
147 contentDescription = hourContentDescription,
148 option = { hour: Int -> Option(0, "%2d".format(hour + 1)) }
149 )
150 Spacer(Modifier.width(8.dp))
151 Text(text = ":", style = textStyle, color = MaterialTheme.colors.onBackground)
152 Spacer(Modifier.width(8.dp))
153 val minuteState =
154 rememberPickerState(initialNumberOfOptions = 60, initiallySelectedOption = 0)
155 val minuteContentDescription by remember {
156 derivedStateOf { "${minuteState.selectedOption} minutes" }
157 }
158 Picker(
159 readOnly = selectedColumn != 1,
160 state = minuteState,
161 modifier = Modifier.size(64.dp, 100.dp),
162 contentDescription = minuteContentDescription,
163 option = { minute: Int -> Option(1, "%02d".format(minute)) }
164 )
165 }
166 }
167