Compose Modifier.swipeable() 写个侧拉组件

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

前言

大家使用 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
            )
        }
        
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值