前言
大家使用 QQ 的时候,肯定见过它:

这次,我想用 Compose 来写一个类似的,大家可以和我一步步来,也可以直接看完整代码。
一、工具选择
在 Compose 里有 SwipeToDismiss、Modifier.swipeable() 两种供我们使用, SwipeToDismiss 的底层使用 swipeable 实现的,使用的时候侧拉会占满一整行,像这样:
和我们想做的不太一致,也和我们平常习惯用的不一样。所以就不使用它了,用 Modifier.swipeable() 来实现。
二、具体实现
1.方法定义
先看看最后方法的定义和它的参数:
/**
* @Description: 侧拉滑动组件
* @Param:
* @param modifier 没啥好说的
* @param swipeItemWidth 侧拉组件的宽度
* @param isShowSwipe 判断是否显示
* @param swipeDirection 判断侧拉方向
* @param swipeContent 侧拉组件的内容
* @param content 主题内容
* @return:
*/
@OptIn(ExperimentalMaterialApi::class, ExperimentalAnimationApi::class)
@Composable
fun SwipeItem(
modifier: Modifier = Modifier,
swipeItemWidth: Float,
isShowSwipe: Boolean = true,
swipeDirection: SwipeDirection = SwipeDirection.ENDTOSTART,
swipeContent: @Composable () -> Unit,
content: @Composable () -> Unit
) {
}
这里的方向定义,我们设置了一个枚举类:
enum class SwipeDirection {
STARTTOEND,
ENDTOSTART
}
表示不同的两个方向。
其他的看看注释应该就懂了。
2.变量准备
// 记录一下滑动方向, 便于下面的判断
val isEndToStart = swipeDirection == SwipeDirection.ENDTOSTART
val swipeState = rememberSwipeableState(initialValue = false)
// 滑动偏移量, 偏移量指 content 的左边的偏移
val dx: Float = if (isEndToStart) {
-swipeItemWidth
} else {
swipeItemWidth
}
// 偏移 dx 时显示, 两个方向不同, 所以上面对 dx 做判断
val anchors = mapOf(dx to true, 0f to false)
Row(modifier = modifier) {
...主体内容和侧拉内容...
}
这里我们定义了一些量,为下面的滑动、侧拉组件显示做准备。要注意的是 dx 的值,因为左拉和右拉的偏移量要与 swipeState 的 true 对应,当偏移距离为 swipeItemWidth 时 swipeState 的 value 就会变成 true,swipeState 的 value 我们会用到侧拉组件的显示与否中去。这里的 anchors 我们一会用到 swipeable() 中去。接下来我们往里填充体内容和侧拉内容就行了。
3.主体内容
代码如下:
Box(
modifier = Modifier
// .fillMaxWidth()
// 这里要用 weight 才会有挤压的效果
// 而且用 fillMaxWidth() 滑动组件会被遮挡
.weight(1f)
.offset {
IntOffset(
swipeState.offset.value.toInt(), 0
)
}

本文详细介绍了如何使用Jetpack Compose构建一个类似QQ消息侧滑删除的功能。通过Modifier.swipeable()实现滑动手势,结合AnimatedVisibility动画展示和隐藏侧拉内容,并通过点击隐藏侧拉项。文章提供了完整的代码示例,展示了从右往左和从左往右滑动的不同效果。
最低0.47元/天 解锁文章
1679

被折叠的 条评论
为什么被折叠?



