Android Compose AnchoredDraggable:监听拖拽至结束锚点完成事件
解决Compose AnchoredDraggable拖拽至结束锚点触发回调的问题
你之前用collectIsDraggedAsState()的方式会在拖拽开始时就触发回调,这是因为该状态在拖拽启动后立即变为true,而非拖拽完成并到达锚点时。正确的做法是直接监听AnchoredDraggableState的锚点状态变化,仅当组件最终停在结束锚点时触发回调。
修改后的代码示例
enum class DragAnchor { START, END } @Composable fun YourDraggableComponent(onDragComplete: () -> Unit) { val density = LocalDensity.current val state = remember { AnchoredDraggableState( initialValue = DragAnchor.START, positionalThreshold = { distance: Float -> distance * 0.5f }, velocityThreshold = { with(density) { 100.dp.toPx() } }, animationSpec = tween(), ) } // 监听锚点状态变化,仅当切换到END锚点时触发回调 LaunchedEffect(state) { snapshotFlow { state.currentValue } .distinctUntilChanged() // 避免重复触发 .filter { it == DragAnchor.END } // 只关注结束锚点 .collect { onDragComplete() } } MyComposable( modifier = Modifier .anchoredDraggable( state = state, orientation = Orientation.Vertical, reverseDirection = false ) ) }
关键说明
- 移除
MutableInteractionSource:不需要通过交互源判断拖拽状态,直接使用AnchoredDraggableState的内置状态更可靠。 snapshotFlow监听状态:snapshotFlow会收集currentValue的变化,配合distinctUntilChanged()避免同一锚点下的重复回调,filter确保只响应结束锚点的切换。LaunchedEffect启动监听:确保监听逻辑在组件生命周期内只启动一次,且重组时不会重复创建流。
如果需要确保回调仅在**拖拽动作完成(而非代码主动设置锚点)**时触发,可以额外结合state.isDragging和state.isAnimationRunning判断:
LaunchedEffect(state) { snapshotFlow { Pair(state.currentValue, state.isAnimationRunning) } .distinctUntilChanged() .filter { (anchor, isAnimating) -> anchor == DragAnchor.END && !isAnimating } .collect { onDragComplete() } }
这个版本会等待拖拽后的动画完全结束,组件稳定停在结束锚点时才触发回调。
内容的提问来源于stack exchange,提问作者pjp94
相关产品推荐
相关产品推荐

