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 .Bold )
6464        SwipeItemExample ()
6565        Text (" Swipe to dismiss with a cross-fade animation" =  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