Skip to content

Commit

Permalink
Add Swipe to reveal examples
Browse files Browse the repository at this point in the history
  • Loading branch information
jakeroseman committed Dec 9, 2024
1 parent c79a414 commit 95e6d36
Showing 1 changed file with 304 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,304 @@
package com.example.compose.snippets.components

import androidx.compose.animation.animateColorAsState
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.CheckBox
import androidx.compose.material.icons.filled.CheckBoxOutlineBlank
import androidx.compose.material.icons.filled.Delete
import androidx.compose.material3.Icon
import androidx.compose.material3.ListItem
import androidx.compose.material3.OutlinedCard
import androidx.compose.material3.SwipeToDismissBox
import androidx.compose.material3.SwipeToDismissBoxValue
import androidx.compose.material3.Text
import androidx.compose.material3.rememberSwipeToDismissBoxState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.graphics.lerp
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp

// [START android_compose_components_todoitem]
data class TodoItem(
var isItemDone: Boolean,
var itemDescription: String
)
// [END android_compose_components_todoitem]

// [START android_compose_components_swipeitem]
@Composable
fun SwipeItem(
value: TodoItem,
startToEndAction: (TodoItem) -> Unit,
endToStartAction: (TodoItem) -> Unit,
modifier: Modifier = Modifier,
content: @Composable (TodoItem) -> Unit
) {
val swipeToDismissBoxState = rememberSwipeToDismissBoxState(
confirmValueChange = {
when (it) {
SwipeToDismissBoxValue.StartToEnd -> {
startToEndAction(value)
// Do not dismiss this item.
false
}
SwipeToDismissBoxValue.EndToStart -> {
endToStartAction(value)
true
}
SwipeToDismissBoxValue.Settled -> {
false
}
}
}
)

SwipeToDismissBox(
state = swipeToDismissBoxState,
modifier = modifier
.fillMaxSize(),
backgroundContent = {
Row(
modifier = Modifier
.background(
when (swipeToDismissBoxState.dismissDirection) {
SwipeToDismissBoxValue.StartToEnd -> {
Color.Blue
}
SwipeToDismissBoxValue.EndToStart -> {
Color.Red
}
SwipeToDismissBoxValue.Settled -> {
Color.LightGray
}
}
)
.fillMaxSize(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween
) {
when (swipeToDismissBoxState.dismissDirection) {
SwipeToDismissBoxValue.StartToEnd -> {
if (value.isItemDone) {
Icon(
imageVector = Icons.Default.CheckBox,
contentDescription = "Item done",
tint = Color.White,
modifier = Modifier
.padding(12.dp)
)
} else {
Icon(
imageVector = Icons.Default.CheckBoxOutlineBlank,
contentDescription = "Item not done",
tint = Color.White,
modifier = Modifier
.padding(12.dp)
)
}
}

SwipeToDismissBoxValue.EndToStart -> {
Spacer(modifier = Modifier)
Icon(
imageVector = Icons.Default.Delete,
contentDescription = "Remove item",
tint = Color.White,
modifier = Modifier
.padding(12.dp)
)
}

SwipeToDismissBoxValue.Settled -> {}
}
}
}
) {
content(value)
}
}
// [END android_compose_components_swipeitem]

@Preview(showBackground = true)
// [START android_compose_components_swipeitemexample]
@Composable
private fun SwipeItemExample() {
val todoItems = remember {
mutableStateListOf(
TodoItem(isItemDone = false, itemDescription = "Pay bills"),
TodoItem(isItemDone = false, itemDescription = "Buy groceries"),
TodoItem(isItemDone = false, itemDescription = "Go to gym"),
TodoItem(isItemDone = false, itemDescription = "Get dinner")
)
}

LazyColumn {
items(
items = todoItems,
key = { it.itemDescription }
) { todoItem ->
SwipeItem(
value = todoItem,
startToEndAction = {
todoItem.isItemDone = !todoItem.isItemDone
},
endToStartAction = {
todoItems -= todoItem
}
) {
ListItem(
headlineContent = { Text(text = todoItem.itemDescription) },
supportingContent = { Text(text = "swipe me to update or remove.") }
)
}
}
}
}
// [END android_compose_components_swipeitemexample]

// [START android_compose_components_swipecarditem]
@Composable
fun SwipeCardItem(
value: TodoItem,
startToEndAction: (TodoItem) -> Unit,
endToStartAction: (TodoItem) -> Unit,
modifier: Modifier = Modifier,
content: @Composable (TodoItem) -> Unit
) {
val swipeToDismissState = rememberSwipeToDismissBoxState(
positionalThreshold = { totalDistance -> totalDistance * 0.25f },
confirmValueChange = {
when (it) {
SwipeToDismissBoxValue.StartToEnd -> {
startToEndAction(value)
// Do not dismiss this item.
false
}
SwipeToDismissBoxValue.EndToStart -> {
endToStartAction(value)
true
}
SwipeToDismissBoxValue.Settled -> {
false
}
}
}
)

SwipeToDismissBox(
modifier = Modifier,
state = swipeToDismissState,
backgroundContent = {
// Cross-fade the background color as the drag gesture progresses.
val color by animateColorAsState(
when (swipeToDismissState.targetValue) {
SwipeToDismissBoxValue.Settled -> Color.LightGray
SwipeToDismissBoxValue.StartToEnd ->
lerp(Color.LightGray, Color.Blue, swipeToDismissState.progress)


SwipeToDismissBoxValue.EndToStart ->
lerp(Color.LightGray, Color.Red, swipeToDismissState.progress)
}, label = "swipeable card item background color"
)
Row(
modifier = Modifier
.background(color)
.fillMaxSize(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween
) {
when (swipeToDismissState.dismissDirection) {
SwipeToDismissBoxValue.StartToEnd -> {
if (value.isItemDone) {
Icon(
imageVector = Icons.Default.CheckBox,
contentDescription = "Item done",
tint = Color.White,
modifier = Modifier
.padding(12.dp)
)
} else {
Icon(
imageVector = Icons.Default.CheckBoxOutlineBlank,
contentDescription = "Item not done",
tint = Color.White,
modifier = Modifier
.padding(12.dp)
)
}
}


SwipeToDismissBoxValue.EndToStart -> {
Spacer(modifier = Modifier)
Icon(
imageVector = Icons.Default.Delete,
contentDescription = "Remove item",
tint = Color.White,
modifier = Modifier
.padding(12.dp)
)
}


SwipeToDismissBoxValue.Settled -> {}
}
}
}) {
content(value)
}
}
// [END android_compose_components_swipecarditem]

// [START android_compose_components_swipecarditemexample]
@Preview
@Composable
private fun SwipeCardItemExample() {
val todoItems = remember {
mutableStateListOf(
TodoItem(isItemDone = false, itemDescription = "Pay bills"),
TodoItem(isItemDone = false, itemDescription = "Buy groceries"),
TodoItem(isItemDone = false, itemDescription = "Go to gym"),
TodoItem(isItemDone = false, itemDescription = "Get dinner")
)
}

LazyColumn {
items(
items = todoItems,
key = { it.itemDescription }
) { todoItem ->
SwipeCardItem(
value = todoItem,
startToEndAction = {
todoItem.isItemDone = !todoItem.isItemDone
},
endToStartAction = {
todoItems -= todoItem
}
) {
OutlinedCard(shape = RectangleShape) {
ListItem(
headlineContent = { Text(todoItem.itemDescription) },
supportingContent = { Text("swipe me to update or remove.") })
}
}
}
}
}
// [END android_compose_components_swipecarditemexample]

0 comments on commit 95e6d36

Please sign in to comment.