1616
1717package com.example.compose.snippets.components
1818
19- import androidx.compose.animation.animateColorAsState
2019import androidx.compose.foundation.background
2120import androidx.compose.foundation.layout.Arrangement
2221import androidx.compose.foundation.layout.Column
23- import androidx.compose.foundation.layout.Row
24- import androidx.compose.foundation.layout.Spacer
2522import androidx.compose.foundation.layout.fillMaxSize
2623import androidx.compose.foundation.layout.padding
24+ import androidx.compose.foundation.layout.wrapContentSize
2725import androidx.compose.foundation.lazy.LazyColumn
2826import androidx.compose.foundation.lazy.items
2927import androidx.compose.material.icons.Icons
@@ -34,15 +32,17 @@ import androidx.compose.material3.Icon
3432import androidx.compose.material3.ListItem
3533import androidx.compose.material3.OutlinedCard
3634import 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
3838import androidx.compose.material3.Text
3939import androidx.compose.material3.rememberSwipeToDismissBoxState
4040import androidx.compose.runtime.Composable
41- import androidx.compose.runtime.getValue
4241import androidx.compose.runtime.mutableStateListOf
4342import androidx.compose.runtime.remember
4443import androidx.compose.ui.Alignment
4544import androidx.compose.ui.Modifier
45+ import androidx.compose.ui.draw.drawBehind
4646import androidx.compose.ui.graphics.Color
4747import androidx.compose.ui.graphics.RectangleShape
4848import androidx.compose.ui.graphics.lerp
@@ -63,102 +63,71 @@ fun SwipeToDismissBoxExamples() {
6363 Text (" Swipe to dismiss with change of background" , fontWeight = FontWeight .Bold )
6464 SwipeItemExample ()
6565 Text (" Swipe to dismiss with a cross-fade animation" , fontWeight = FontWeight .Bold )
66- SwipeCardItemExample ()
66+ SwipeItemWithAnimationExample ()
6767 }
6868}
6969
7070// [START android_compose_components_todoitem]
7171data class TodoItem (
72- var isItemDone : Boolean ,
73- var itemDescription : String
72+ val itemDescription : String ,
73+ var isItemDone : Boolean = false
7474)
7575// [END android_compose_components_todoitem]
7676
7777// [START android_compose_components_swipeitem]
7878@Composable
79- fun SwipeItem (
79+ fun TodoListItem (
8080 todoItem : TodoItem ,
81- startToEndAction : (TodoItem ) -> Unit ,
82- endToStartAction : (TodoItem ) -> Unit ,
81+ onToggleDone : (TodoItem ) -> Unit ,
82+ onRemove : (TodoItem ) -> Unit ,
8383 modifier : Modifier = Modifier ,
84- content : @Composable (TodoItem ) -> Unit
8584) {
8685 val swipeToDismissBoxState = rememberSwipeToDismissBoxState(
8786 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
10291 }
10392 )
10493
10594 SwipeToDismissBox (
10695 state = swipeToDismissBoxState,
10796 modifier = modifier.fillMaxSize(),
10897 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
123109 )
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 -> {}
157110 }
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 -> {}
158124 }
159125 }
160126 ) {
161- content(todoItem)
127+ ListItem (
128+ headlineContent = { Text (todoItem.itemDescription) },
129+ supportingContent = { Text (" swipe me to update or remove." ) }
130+ )
162131 }
163132}
164133// [END android_compose_components_swipeitem]
@@ -169,10 +138,8 @@ fun SwipeItem(
169138private fun SwipeItemExample () {
170139 val todoItems = remember {
171140 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" )
176143 )
177144 }
178145
@@ -181,124 +148,91 @@ private fun SwipeItemExample() {
181148 items = todoItems,
182149 key = { it.itemDescription }
183150 ) { todoItem ->
184- SwipeItem (
151+ TodoListItem (
185152 todoItem = todoItem,
186- startToEndAction = {
153+ onToggleDone = { todoItem ->
187154 todoItem.isItemDone = ! todoItem.isItemDone
188155 },
189- endToStartAction = {
156+ onRemove = { todoItem ->
190157 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+ )
198161 }
199162 }
200163}
201164// [END android_compose_components_swipeitemexample]
202165
203166// [START android_compose_components_swipecarditem]
204167@Composable
205- fun SwipeCardItem (
168+ fun TodoListItemWithAnimation (
206169 todoItem : TodoItem ,
207- startToEndAction : (TodoItem ) -> Unit ,
208- endToStartAction : (TodoItem ) -> Unit ,
170+ onToggleDone : (TodoItem ) -> Unit ,
171+ onRemove : (TodoItem ) -> Unit ,
209172 modifier : Modifier = Modifier ,
210- content : @Composable (TodoItem ) -> Unit
211173) {
212- val swipeToDismissState = rememberSwipeToDismissBoxState(
213- positionalThreshold = { totalDistance -> totalDistance * 0.25f },
214- // [START_EXCLUDE]
174+ val swipeToDismissBoxState = rememberSwipeToDismissBoxState(
215175 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
230180 }
231181 )
232182
233- // [END_EXCLUDE]
234183 SwipeToDismissBox (
235- modifier = Modifier ,
236- state = swipeToDismissState ,
184+ state = swipeToDismissBoxState ,
185+ modifier = modifier.fillMaxSize() ,
237186 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+ )
282201 }
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 -> {}
283215 }
284216 }
285217 ) {
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+ }
287224 }
288- // [END_EXCLUDE]
289225}
290226// [END android_compose_components_swipecarditem]
291227
292- // [START android_compose_components_swipecarditemexample]
293228@Preview
229+ // [START android_compose_components_swipecarditemexample]
294230@Composable
295- private fun SwipeCardItemExample () {
231+ private fun SwipeItemWithAnimationExample () {
296232 val todoItems = remember {
297233 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" )
302236 )
303237 }
304238
@@ -307,22 +241,16 @@ private fun SwipeCardItemExample() {
307241 items = todoItems,
308242 key = { it.itemDescription }
309243 ) { todoItem ->
310- SwipeCardItem (
244+ TodoListItemWithAnimation (
311245 todoItem = todoItem,
312- startToEndAction = {
246+ onToggleDone = { todoItem ->
313247 todoItem.isItemDone = ! todoItem.isItemDone
314248 },
315- endToStartAction = {
249+ onRemove = { todoItem ->
316250 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+ )
326254 }
327255 }
328256}
0 commit comments