-
-
Save bmc08gt/fca95db3bf9fcf255d76f03ec10ea3f9 to your computer and use it in GitHub Desktop.
import androidx.compose.animation.* | |
import androidx.compose.animation.core.tween | |
import androidx.compose.material.* | |
import androidx.compose.runtime.Composable | |
import androidx.compose.runtime.onCommit | |
import androidx.compose.ui.Modifier | |
@OptIn(ExperimentalAnimationApi::class, ExperimentalMaterialApi::class) | |
@Composable | |
fun <T> AnimatedSwipeDismiss( | |
modifier: Modifier = Modifier, | |
item: T, | |
background: @Composable (isDismissed: Boolean) -> Unit, | |
content: @Composable (isDismissed: Boolean) -> Unit, | |
directions: Set<DismissDirection> = setOf(DismissDirection.EndToStart), | |
enter: EnterTransition = expandVertically(), | |
exit: ExitTransition = shrinkVertically( | |
animSpec = tween( | |
durationMillis = 500, | |
) | |
), | |
onDismiss: (T) -> Unit | |
) { | |
val dismissState = rememberDismissState() | |
val isDismissed = dismissState.isDismissed(DismissDirection.EndToStart) | |
onCommit(dismissState.value) { | |
if (dismissState.value == DismissValue.DismissedToStart) { | |
onDismiss(item) | |
} | |
} | |
AnimatedVisibility( | |
modifier = modifier, | |
visible = !isDismissed, | |
enter = enter, | |
exit = exit | |
) { | |
SwipeToDismiss( | |
modifier = modifier, | |
state = dismissState, | |
directions = directions, | |
background = { background(isDismissed) }, | |
dismissContent = { content(isDismissed) } | |
) | |
} | |
} |
@Composable | |
fun <T> ListContent( | |
innerPadding: InnerPadding, | |
items: List<T>, | |
onSwipe: (T) -> Unit, | |
onClick: (T) -> Unit | |
) { | |
LazyColumnFor( | |
modifier = modifier.padding(innerPadding), | |
items = items, | |
) { item -> | |
AnimatedSwipeDismiss( | |
item = item, | |
background = { isDismissed -> | |
/** define your background delete view here | |
* possibly: | |
Box( | |
modifier = Modifier.fillMaxSize(), | |
backgroundColor = Color.Red, | |
paddingStart = 20.dp, | |
paddingEnd = 20.dp, | |
gravity = ContentGravity.CenterEnd | |
) { | |
val alpha = animate( if (isDismissed) 0f else 1f) | |
Icon(Icons.Filled.Delete, tint = Color.White.copy(alpha = alpha)) | |
} | |
using isDismissed to control alpha of the icon or content in the box | |
*/ | |
}, | |
content = { /* your item cell (feed your on click here) */ }, | |
onDismiss = { onSwipe(it) } | |
} | |
} |
function ListContent(
in ListContent.kt
should be fun <T> ListContent(
for this to compile.
Edit: also missing a closing parentheses for the AnimatedSwipeDismiss invocation in the same file. Final version that compiles:
@Composable
fun <T> ListContent(
innerPadding: PaddingValues,
items: List<T>,
onSwipe: (T) -> Unit,
onClick: (T) -> Unit,
modifier: Modifier = Modifier,
) {
LazyColumnFor(
modifier = modifier.padding(innerPadding),
items = items,
) { item ->
AnimatedSwipeDismiss(
item = item,
background = { isDismissed ->
/** define your background delete view here
* possibly:
Box(
modifier = Modifier.fillMaxSize(),
backgroundColor = Color.Red,
paddingStart = 20.dp,
paddingEnd = 20.dp,
gravity = ContentGravity.CenterEnd
) {
val alpha = animate( if (isDismissed) 0f else 1f)
Icon(Icons.Filled.Delete, tint = Color.White.copy(alpha = alpha))
}
using isDismissed to control alpha of the icon or content in the box
*/
},
content = { /* your item cell (feed your on click here) */ },
onDismiss = { onSwipe(it) }
)
}
}
function ListContent(
inListContent.kt
should befun <T> ListContent(
for this to compile.Edit: also missing a closing parentheses for the AnimatedSwipeDismiss invocation in the same file. Final version that compiles:
@Composable fun <T> ListContent( innerPadding: PaddingValues, items: List<T>, onSwipe: (T) -> Unit, onClick: (T) -> Unit, modifier: Modifier = Modifier, ) { LazyColumnFor( modifier = modifier.padding(innerPadding), items = items, ) { item -> AnimatedSwipeDismiss( item = item, background = { isDismissed -> /** define your background delete view here * possibly: Box( modifier = Modifier.fillMaxSize(), backgroundColor = Color.Red, paddingStart = 20.dp, paddingEnd = 20.dp, gravity = ContentGravity.CenterEnd ) { val alpha = animate( if (isDismissed) 0f else 1f) Icon(Icons.Filled.Delete, tint = Color.White.copy(alpha = alpha)) } using isDismissed to control alpha of the icon or content in the box */ }, content = { /* your item cell (feed your on click here) */ }, onDismiss = { onSwipe(it) } ) } }
Thanks! Copy/paste fail - updated
I've found val dismissState = rememberDismissState()
remembering the dismissed state after the item was deleted from the List items
. I've changed it to val dissmissState = remember { DismissState(...) }
as a workaround.
Hey @bmc08gt,
Thanks for this code snippet but androidx.compose.runtime.onCommit is deprecated and removed in the latest compose stable versions (tested on compose version 1.0.5), so I've updated the snippet for AnimatedSwipeDismiss.kt, please consider updating your version.
import androidx.compose.animation.core.tween
import androidx.compose.material.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.SideEffect
import androidx.compose.ui.Modifier
@ExperimentalMaterialApi
@ExperimentalAnimationApi
@Composable
fun <T> AnimatedSwipeDismiss(
modifier: Modifier = Modifier,
item: T,
background: @Composable (isDismissed: Boolean) -> Unit,
content: @Composable (isDismissed: Boolean) -> Unit,
directions: Set<DismissDirection> = setOf(DismissDirection.EndToStart),
enter: EnterTransition = expandVertically(),
exit: ExitTransition = shrinkVertically(
animationSpec = tween(
durationMillis = 500,
)
),
onDismiss: (T) -> Unit
) {
val dismissState = rememberDismissState()
val isDismissed = dismissState.isDismissed(DismissDirection.EndToStart)
SideEffect {
if (dismissState.isDismissed(DismissDirection.EndToStart)) {
onDismiss(item)
}
}
AnimatedVisibility(
modifier = modifier,
visible = !isDismissed,
enter = enter,
exit = exit
) {
SwipeToDismiss(
modifier = modifier,
state = dismissState,
directions = directions,
background = { background(isDismissed) },
dismissContent = { content(isDismissed) }
)
}
}
Thanks Louis!