Flutter如何让Slider组件实现类似SeekBar的音视频进度调节效果
问题根源
你的滑块拖拽异常是因为播放过程中just_audio的positionStream会持续推送最新播放位置,触发Provider更新currentPosition,而Slider的value直接绑定了这个实时更新的变量,拖拽时滑块位置会被实时拉回当前播放进度,就出现了反向跳动的异常效果。
解决方案
无需修改Provider层的监听逻辑,只需要在Slider所在的Widget层增加临时状态控制拖拽过程中的滑块显示即可,实现和主流播放器一致的交互效果:
- 将Slider所在的Widget改为
StatefulWidget,新增两个局部变量标记拖拽状态和临时拖拽值 - 拖拽过程中优先用局部临时值控制滑块位置,不受Provider实时进度更新影响
- 拖拽结束后再触发seek操作,恢复和Provider进度的绑定
调整后的Slider代码
// StatefulWidget 内部定义的局部变量 bool _isDragging = false; double _dragValue = 0; // 替换你原来的SliderTheme部分 SliderTheme( data: SliderThemeData( trackHeight: 3, thumbShape: RoundSliderThumbShape(enabledThumbRadius: 8), thumbColor: kWhiteColor, activeTrackColor: kPrimaryColor, inactiveTrackColor: kWhiteColor.withOpacity(0.5), overlayColor: kPrimaryColor.withOpacity(0.1), trackShape: AppCustomTrackShape(), ), child: Slider( max: mediaProvider.totalDuration.inSeconds.toDouble(), // 拖拽时用局部临时值,否则用Provider的实时进度 value: _isDragging ? _dragValue : mediaProvider.currentPosition.inSeconds.toDouble(), // 拖拽开始,标记状态 onChangeStart: (value) { setState(() { _isDragging = true; _dragValue = value; }); }, // 拖拽过程中只更新局部临时值,不触发seek onChanged: (value) { setState(() { _dragValue = value; }); }, // 拖拽结束,恢复状态并触发seek onChangeEnd: (value) async { setState(() { _isDragging = false; }); await mediaProvider.seekAudioPlayer(value); }, ), )
可选优化
如果需要拖拽过程中暂停全局进度更新,可在Provider中新增拖拽标记控制监听逻辑:
// 你的Provider类中新增变量 bool _isDragging = false; // 修改positionStream监听 audioPlayer.positionStream.listen((Duration duration) { // 拖拽时不更新全局进度 if(!_isDragging) { updateCurrentPosition(duration); } }); // 新增拖拽状态控制方法 void setDragging(bool isDragging) { _isDragging = isDragging; notifyListeners(); }
然后在Slider的onChangeStart和onChangeEnd中调用mediaProvider.setDragging方法同步状态即可。
内容的提问来源于stack exchange,提问作者Rezia
相关产品推荐
相关产品推荐

