该技能属于 Kotlin 与 Jetpack Compose 场景,核心思路是由进度指示器负责绘制,再叠加一层透明手势层,把触点位置映射为 0 到 1 的比例,从而得到一个可拖动定位的 scrubber。它适合视觉上没有对应滑块样式、或需要自定义点击区域与手势消费策略的媒体播放场景。
主要能力包括:把指示器放入固定高度(如 40dp)的容器中并居中,让手势挂在容器上,以获得远超视觉高度的可触摸区域;在水平拖拽中调用 change.consume(),防止外层 HorizontalPager 或可拖拽面板在阈值被触发时抢走手势;交互期间以拖拽比例为准,避免播放器持续发布的位置与手指争夺显示;把点击与拖拽拆成两个 pointerInput 块,点击可立即提交并发出完成回调;在 onDragEnd 与 onDragCancel 中都清除交互标志,避免取消后进度条冻结;用 widthPx <= 0 的判断防止首帧除以零;放置滑块时减去滑块自身宽度,避免在轨道末端溢出;在 offset 的 lambda 中计算位置,使滑块形态变化时自动重新定位。
使用方式上,代码示例展示了 Box 容器配合 onSizeChanged、detectTapGestures 与 detectHorizontalDragGestures,以及用 displayedFraction 在交互比例与进度比例之间切换。装饰效果(如波纹、光晕)需在绘制比例为 0 时消失。内部统一使用 0..1 比例,仅在回调边界转换为应用使用的 0..100 百分比。若仅需调整视觉位置,应使用 Modifier.offset 等绘制期修饰符,而不改变测量或缩小触摸区域。
限制方面:该方案放弃了滑块自带的无障碍语义,控件不可聚焦、不播报数值、不响应键盘,如需这些能力必须显式添加 Modifier.semantics 与 setProgress 动作。当平台滑块已能满足需求时,技能建议改用 custom-thin-media-slider,以保留语义与键盘处理。技能还给出 grep 命令用于检查每个水平拖拽检测器是否配有 consume、两条交互结束路径是否都清除标志,以及手动验证步骤:靠近右边缘点击、拖动中途暂停、拖出控件继续拖动、在窗口外松手等。