16
16
17
17
package com.example.compose.snippets.components
18
18
19
- import androidx.compose.animation.animateColorAsState
20
19
import androidx.compose.foundation.background
21
20
import androidx.compose.foundation.layout.Arrangement
22
21
import androidx.compose.foundation.layout.Column
23
- import androidx.compose.foundation.layout.Row
24
- import androidx.compose.foundation.layout.Spacer
25
22
import androidx.compose.foundation.layout.fillMaxSize
26
23
import androidx.compose.foundation.layout.padding
24
+ import androidx.compose.foundation.layout.wrapContentSize
27
25
import androidx.compose.foundation.lazy.LazyColumn
28
26
import androidx.compose.foundation.lazy.items
29
27
import androidx.compose.material.icons.Icons
@@ -34,15 +32,17 @@ import androidx.compose.material3.Icon
34
32
import androidx.compose.material3.ListItem
35
33
import androidx.compose.material3.OutlinedCard
36
34
import androidx.compose.material3.SwipeToDismissBox
37
- import androidx.compose.material3.SwipeToDismissBoxValue
35
+ import androidx.compose.material3.SwipeToDismissBoxValue.EndToStart
36
+ import androidx.compose.material3.SwipeToDismissBoxValue.Settled
37
+ import androidx.compose.material3.SwipeToDismissBoxValue.StartToEnd
38
38
import androidx.compose.material3.Text
39
39
import androidx.compose.material3.rememberSwipeToDismissBoxState
40
40
import androidx.compose.runtime.Composable
41
- import androidx.compose.runtime.getValue
42
41
import androidx.compose.runtime.mutableStateListOf
43
42
import androidx.compose.runtime.remember
44
43
import androidx.compose.ui.Alignment
45
44
import androidx.compose.ui.Modifier
45
+ import androidx.compose.ui.draw.drawBehind
46
46
import androidx.compose.ui.graphics.Color
47
47
import androidx.compose.ui.graphics.RectangleShape
48
48
import androidx.compose.ui.graphics.lerp
@@ -63,102 +63,71 @@ fun SwipeToDismissBoxExamples() {
63
63
Text (" Swipe to dismiss with change of background" , fontWeight = FontWeight .Bold )
64
64
SwipeItemExample ()
65
65
Text (" Swipe to dismiss with a cross-fade animation" , fontWeight = FontWeight .Bold )
66
- SwipeCardItemExample ()
66
+ SwipeItemWithAnimationExample ()
67
67
}
68
68
}
69
69
70
70
// [START android_compose_components_todoitem]
71
71
data class TodoItem (
72
- var isItemDone : Boolean ,
73
- var itemDescription : String
72
+ val itemDescription : String ,
73
+ var isItemDone : Boolean = false
74
74
)
75
75
// [END android_compose_components_todoitem]
76
76
77
77
// [START android_compose_components_swipeitem]
78
78
@Composable
79
- fun SwipeItem (
79
+ fun TodoListItem (
80
80
todoItem : TodoItem ,
81
- startToEndAction : (TodoItem ) -> Unit ,
82
- endToStartAction : (TodoItem ) -> Unit ,
81
+ onToggleDone : (TodoItem ) -> Unit ,
82
+ onRemove : (TodoItem ) -> Unit ,
83
83
modifier : Modifier = Modifier ,
84
- content : @Composable (TodoItem ) -> Unit
85
84
) {
86
85
val swipeToDismissBoxState = rememberSwipeToDismissBoxState(
87
86
confirmValueChange = {
88
- when (it) {
89
- SwipeToDismissBoxValue .StartToEnd -> {
90
- startToEndAction(todoItem)
91
- // Do not dismiss this item.
92
- false
93
- }
94
- SwipeToDismissBoxValue .EndToStart -> {
95
- endToStartAction(todoItem)
96
- true
97
- }
98
- SwipeToDismissBoxValue .Settled -> {
99
- false
100
- }
101
- }
87
+ if (it == StartToEnd ) onToggleDone(todoItem)
88
+ else if (it == EndToStart ) onRemove(todoItem)
89
+ // Reset item when toggling done status
90
+ it != StartToEnd
102
91
}
103
92
)
104
93
105
94
SwipeToDismissBox (
106
95
state = swipeToDismissBoxState,
107
96
modifier = modifier.fillMaxSize(),
108
97
backgroundContent = {
109
- Row (
110
- modifier = Modifier
111
- .background(
112
- when (swipeToDismissBoxState.dismissDirection) {
113
- SwipeToDismissBoxValue .StartToEnd -> {
114
- Color .Blue
115
- }
116
- SwipeToDismissBoxValue .EndToStart -> {
117
- Color .Red
118
- }
119
- SwipeToDismissBoxValue .Settled -> {
120
- Color .LightGray
121
- }
122
- }
98
+ when (swipeToDismissBoxState.dismissDirection) {
99
+ StartToEnd -> {
100
+ Icon (
101
+ if (todoItem.isItemDone) Icons .Default .CheckBox else Icons .Default .CheckBoxOutlineBlank ,
102
+ contentDescription = if (todoItem.isItemDone) " Done" else " Not done" ,
103
+ modifier = Modifier
104
+ .fillMaxSize()
105
+ .background(Color .Blue )
106
+ .wrapContentSize(Alignment .CenterStart )
107
+ .padding(12 .dp),
108
+ tint = Color .White
123
109
)
124
- .fillMaxSize(),
125
- verticalAlignment = Alignment .CenterVertically ,
126
- horizontalArrangement = Arrangement .SpaceBetween
127
- ) {
128
- when (swipeToDismissBoxState.dismissDirection) {
129
- SwipeToDismissBoxValue .StartToEnd -> {
130
- val icon = if (todoItem.isItemDone) {
131
- Icons .Default .CheckBox
132
- } else {
133
- Icons .Default .CheckBoxOutlineBlank
134
- }
135
-
136
- val contentDescription = if (todoItem.isItemDone) " Done" else " Not done"
137
-
138
- Icon (
139
- icon,
140
- contentDescription,
141
- Modifier .padding(12 .dp),
142
- tint = Color .White
143
- )
144
- }
145
-
146
- SwipeToDismissBoxValue .EndToStart -> {
147
- Spacer (modifier = Modifier )
148
- Icon (
149
- imageVector = Icons .Default .Delete ,
150
- contentDescription = " Remove item" ,
151
- tint = Color .White ,
152
- modifier = Modifier .padding(12 .dp)
153
- )
154
- }
155
-
156
- SwipeToDismissBoxValue .Settled -> {}
157
110
}
111
+ EndToStart -> {
112
+ Icon (
113
+ imageVector = Icons .Default .Delete ,
114
+ contentDescription = " Remove item" ,
115
+ modifier = Modifier
116
+ .fillMaxSize()
117
+ .background(Color .Red )
118
+ .wrapContentSize(Alignment .CenterEnd )
119
+ .padding(12 .dp),
120
+ tint = Color .White
121
+ )
122
+ }
123
+ Settled -> {}
158
124
}
159
125
}
160
126
) {
161
- content(todoItem)
127
+ ListItem (
128
+ headlineContent = { Text (todoItem.itemDescription) },
129
+ supportingContent = { Text (" swipe me to update or remove." ) }
130
+ )
162
131
}
163
132
}
164
133
// [END android_compose_components_swipeitem]
@@ -169,10 +138,8 @@ fun SwipeItem(
169
138
private fun SwipeItemExample () {
170
139
val todoItems = remember {
171
140
mutableStateListOf(
172
- TodoItem (isItemDone = false , itemDescription = " Pay bills" ),
173
- TodoItem (isItemDone = false , itemDescription = " Buy groceries" ),
174
- TodoItem (isItemDone = false , itemDescription = " Go to gym" ),
175
- TodoItem (isItemDone = false , itemDescription = " Get dinner" )
141
+ TodoItem (" Pay bills" ), TodoItem (" Buy groceries" ),
142
+ TodoItem (" Go to gym" ), TodoItem (" Get dinner" )
176
143
)
177
144
}
178
145
@@ -181,124 +148,91 @@ private fun SwipeItemExample() {
181
148
items = todoItems,
182
149
key = { it.itemDescription }
183
150
) { todoItem ->
184
- SwipeItem (
151
+ TodoListItem (
185
152
todoItem = todoItem,
186
- startToEndAction = {
153
+ onToggleDone = { todoItem ->
187
154
todoItem.isItemDone = ! todoItem.isItemDone
188
155
},
189
- endToStartAction = {
156
+ onRemove = { todoItem ->
190
157
todoItems - = todoItem
191
- }
192
- ) {
193
- ListItem (
194
- headlineContent = { Text (text = todoItem.itemDescription) },
195
- supportingContent = { Text (text = " swipe me to update or remove." ) }
196
- )
197
- }
158
+ },
159
+ modifier = Modifier .animateItem()
160
+ )
198
161
}
199
162
}
200
163
}
201
164
// [END android_compose_components_swipeitemexample]
202
165
203
166
// [START android_compose_components_swipecarditem]
204
167
@Composable
205
- fun SwipeCardItem (
168
+ fun TodoListItemWithAnimation (
206
169
todoItem : TodoItem ,
207
- startToEndAction : (TodoItem ) -> Unit ,
208
- endToStartAction : (TodoItem ) -> Unit ,
170
+ onToggleDone : (TodoItem ) -> Unit ,
171
+ onRemove : (TodoItem ) -> Unit ,
209
172
modifier : Modifier = Modifier ,
210
- content : @Composable (TodoItem ) -> Unit
211
173
) {
212
- val swipeToDismissState = rememberSwipeToDismissBoxState(
213
- positionalThreshold = { totalDistance -> totalDistance * 0.25f },
214
- // [START_EXCLUDE]
174
+ val swipeToDismissBoxState = rememberSwipeToDismissBoxState(
215
175
confirmValueChange = {
216
- when (it) {
217
- SwipeToDismissBoxValue .StartToEnd -> {
218
- startToEndAction(todoItem)
219
- // Do not dismiss this item.
220
- false
221
- }
222
- SwipeToDismissBoxValue .EndToStart -> {
223
- endToStartAction(todoItem)
224
- true
225
- }
226
- SwipeToDismissBoxValue .Settled -> {
227
- false
228
- }
229
- }
176
+ if (it == StartToEnd ) onToggleDone(todoItem)
177
+ else if (it == EndToStart ) onRemove(todoItem)
178
+ // Reset item when toggling done status
179
+ it != StartToEnd
230
180
}
231
181
)
232
182
233
- // [END_EXCLUDE]
234
183
SwipeToDismissBox (
235
- modifier = Modifier ,
236
- state = swipeToDismissState ,
184
+ state = swipeToDismissBoxState ,
185
+ modifier = modifier.fillMaxSize() ,
237
186
backgroundContent = {
238
- // Cross-fade the background color as the drag gesture progresses.
239
- val color by animateColorAsState(
240
- when (swipeToDismissState.targetValue) {
241
- SwipeToDismissBoxValue .Settled -> Color .LightGray
242
- SwipeToDismissBoxValue .StartToEnd ->
243
- lerp(Color .LightGray , Color .Blue , swipeToDismissState.progress)
244
-
245
- SwipeToDismissBoxValue .EndToStart ->
246
- lerp(Color .LightGray , Color .Red , swipeToDismissState.progress)
247
- },
248
- label = " swipeable card item background color"
249
- )
250
- // [START_EXCLUDE]
251
- Row (
252
- modifier = Modifier
253
- .background(color)
254
- .fillMaxSize(),
255
- verticalAlignment = Alignment .CenterVertically ,
256
- horizontalArrangement = Arrangement .SpaceBetween
257
- ) {
258
- when (swipeToDismissState.dismissDirection) {
259
- SwipeToDismissBoxValue .StartToEnd -> {
260
- val icon = if (todoItem.isItemDone) {
261
- Icons .Default .CheckBox
262
- } else {
263
- Icons .Default .CheckBoxOutlineBlank
264
- }
265
-
266
- val contentDescription = if (todoItem.isItemDone) " Done" else " Not done"
267
-
268
- Icon (icon, contentDescription, Modifier .padding(12 .dp), tint = Color .White )
269
- }
270
-
271
- SwipeToDismissBoxValue .EndToStart -> {
272
- Spacer (modifier = Modifier )
273
- Icon (
274
- imageVector = Icons .Default .Delete ,
275
- contentDescription = " Remove item" ,
276
- tint = Color .White ,
277
- modifier = Modifier .padding(12 .dp)
278
- )
279
- }
280
-
281
- SwipeToDismissBoxValue .Settled -> {}
187
+ when (swipeToDismissBoxState.dismissDirection) {
188
+ StartToEnd -> {
189
+ Icon (
190
+ if (todoItem.isItemDone) Icons .Default .CheckBox else Icons .Default .CheckBoxOutlineBlank ,
191
+ contentDescription = if (todoItem.isItemDone) " Done" else " Not done" ,
192
+ modifier = Modifier
193
+ .fillMaxSize()
194
+ .drawBehind {
195
+ drawRect(lerp(Color .LightGray , Color .Blue , swipeToDismissBoxState.progress))
196
+ }
197
+ .wrapContentSize(Alignment .CenterStart )
198
+ .padding(12 .dp),
199
+ tint = Color .White
200
+ )
282
201
}
202
+ EndToStart -> {
203
+ Icon (
204
+ imageVector = Icons .Default .Delete ,
205
+ contentDescription = " Remove item" ,
206
+ modifier = Modifier
207
+ .fillMaxSize()
208
+ .background(lerp(Color .LightGray , Color .Red , swipeToDismissBoxState.progress))
209
+ .wrapContentSize(Alignment .CenterEnd )
210
+ .padding(12 .dp),
211
+ tint = Color .White
212
+ )
213
+ }
214
+ Settled -> {}
283
215
}
284
216
}
285
217
) {
286
- content(todoItem)
218
+ OutlinedCard (shape = RectangleShape ) {
219
+ ListItem (
220
+ headlineContent = { Text (todoItem.itemDescription) },
221
+ supportingContent = { Text (" swipe me to update or remove." ) }
222
+ )
223
+ }
287
224
}
288
- // [END_EXCLUDE]
289
225
}
290
226
// [END android_compose_components_swipecarditem]
291
227
292
- // [START android_compose_components_swipecarditemexample]
293
228
@Preview
229
+ // [START android_compose_components_swipecarditemexample]
294
230
@Composable
295
- private fun SwipeCardItemExample () {
231
+ private fun SwipeItemWithAnimationExample () {
296
232
val todoItems = remember {
297
233
mutableStateListOf(
298
- TodoItem (isItemDone = false , itemDescription = " Pay bills" ),
299
- TodoItem (isItemDone = false , itemDescription = " Buy groceries" ),
300
- TodoItem (isItemDone = false , itemDescription = " Go to gym" ),
301
- TodoItem (isItemDone = false , itemDescription = " Get dinner" )
234
+ TodoItem (" Pay bills" ), TodoItem (" Buy groceries" ),
235
+ TodoItem (" Go to gym" ), TodoItem (" Get dinner" )
302
236
)
303
237
}
304
238
@@ -307,22 +241,16 @@ private fun SwipeCardItemExample() {
307
241
items = todoItems,
308
242
key = { it.itemDescription }
309
243
) { todoItem ->
310
- SwipeCardItem (
244
+ TodoListItemWithAnimation (
311
245
todoItem = todoItem,
312
- startToEndAction = {
246
+ onToggleDone = { todoItem ->
313
247
todoItem.isItemDone = ! todoItem.isItemDone
314
248
},
315
- endToStartAction = {
249
+ onRemove = { todoItem ->
316
250
todoItems - = todoItem
317
- }
318
- ) {
319
- OutlinedCard (shape = RectangleShape ) {
320
- ListItem (
321
- headlineContent = { Text (todoItem.itemDescription) },
322
- supportingContent = { Text (" swipe me to update or remove." ) }
323
- )
324
- }
325
- }
251
+ },
252
+ modifier = Modifier .animateItem()
253
+ )
326
254
}
327
255
}
328
256
}
0 commit comments