flutter - 为什么 Flutter 的 Xlider Range Slider 上的 Handler 在我拖动它们后总是弹回?
问题描述
我正在尝试使用 Xlider 来控制 Flutter 的Audioplayers
插件。但是每次我尝试在 Flutter 的Xlider
Range Slider 上拖动任一处理程序时,它们都会弹回边缘。我Audioplayers
通过Flutter Audio Recorder
插件将录制文件的持续时间传递为final Duration recordedDuration
. 这个记录的持续时间被转换为双精度并用作 Xlider 值参数中的“结束”变量。当_durationSubscription
感知到持续时间的变化时,(当一个新的音频文件被录制时)我做一个 setState 的recordedDuration = duration
. 这似乎将正确的开始和结束值输入 Xlider。从那里开始,我希望下层处理程序中的任何更改都可以更改音频播放器播放的开始位置。但不幸的是,当我放置任何音频功能时,例如;
`_audioPlayer.seek(Duration(milliseconds:600));`
处理程序不会粘在它们被拖动的位置并弹回外边缘。这是整个代码;
class PlayerWidget extends StatefulWidget {
final String url;
final PlayerMode mode;
final Duration recordedDuration;
const PlayerWidget({
Key? key,
required this.url,
this.mode = PlayerMode.MEDIA_PLAYER,
required this.recordedDuration
}) : super(key: key);
@override
State<StatefulWidget> createState() {
return _PlayerWidgetState(url, mode, recordedDuration);
}
}
class _PlayerWidgetState extends State<PlayerWidget> {
String url;
PlayerMode mode;
Duration recordedDuration;
late AudioPlayer _audioPlayer;
PlayerState? _audioPlayerState;
Duration _duration = Duration(microseconds: 1);
Duration _position = Duration(microseconds: 1);
PlayerState _playerState = PlayerState.STOPPED;
StreamSubscription? _durationSubscription;
StreamSubscription? _positionSubscription;
StreamSubscription? _playerCompleteSubscription;
StreamSubscription? _playerErrorSubscription;
StreamSubscription? _playerStateSubscription;
StreamSubscription<PlayerControlCommand>? _playerControlCommandSubscription;
bool get _isPlaying => _playerState == PlayerState.PLAYING;
_PlayerWidgetState(this.url, this.mode, this.recordedDuration);
@override
void initState() {
super.initState();
_initAudioPlayer();
}
@override
void dispose() {
_audioPlayer.dispose();
_durationSubscription?.cancel();
_positionSubscription?.cancel();
_playerCompleteSubscription?.cancel();
_playerErrorSubscription?.cancel();
_playerStateSubscription?.cancel();
_playerControlCommandSubscription?.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
double durationToDouble = recordedDuration.inMilliseconds.toDouble();
double start = 1;
double end = durationToDouble;
return FlutterSlider(
trackBar: FlutterSliderTrackBar(),
handler: FlutterSliderHandler(
child: Icon(Icons.chevron_left, color: Colors.black, size: 32),
),
rightHandler: FlutterSliderHandler(
child: Icon(Icons.chevron_right, color: Colors.black, size: 32),
),
values: [start, end],
min: 1,
max: recordedDuration.inMilliseconds.toDouble(),
rangeSlider: true,
step: FlutterSliderStep(step: 1),
onDragging: (handlerIndex, lowerValue, upperValue) {},
onDragCompleted:(handlerIndex, lowerValue, upperValue){
_audioPlayer.seek(Duration(milliseconds:600));
},
);
}
void _initAudioPlayer() {
_audioPlayer = AudioPlayer(mode: mode);
_durationSubscription = _audioPlayer.onDurationChanged.listen((duration) {
setState(() {
_duration = duration;
recordedDuration = duration;
});
});
_positionSubscription =
_audioPlayer.onAudioPositionChanged.listen((p) => setState(() {
_position = p;
}));
_playerCompleteSubscription =
_audioPlayer.onPlayerCompletion.listen((event) {
_onComplete();
setState(() {
_position = _duration;
});
});
_playerErrorSubscription = _audioPlayer.onPlayerError.listen((msg) {
setState(() {
_playerState = PlayerState.STOPPED;
_duration = const Duration();
_position = const Duration();
});
});
_playerControlCommandSubscription =
_audioPlayer.notificationService.onPlayerCommand.listen((command) {
print('command: $command');
});
_audioPlayer.onPlayerStateChanged.listen((state) {
if (mounted) {
setState(() {
_audioPlayerState = state;
});
}
});
_audioPlayer.onNotificationPlayerStateChanged.listen((state) {
if (mounted) {
setState(() => _audioPlayerState = state);
}
});
}
Future<int> _play() async {
_duration = recordedDuration;
final playPosition = (_position != null &&
_duration != null &&
_position.inMilliseconds > 0 &&
_position.inMilliseconds < _duration.inMilliseconds)
? _position
: null;
final result = await _audioPlayer.play(url, position: playPosition);
if (result == 1) {
setState(() {
_playerState = PlayerState.PLAYING;
});
}
_audioPlayer.setPlaybackRate();
return result;
}
Future<int> _pause() async {
final result = await _audioPlayer.pause();
if (result == 1) {
setState(() {
_playerState = PlayerState.PAUSED;
});
}
return result;
}
void _onComplete() {
setState(() {
_playerState = PlayerState.STOPPED;
});
}
}
我如何让处理程序在我拖动它们后保持不动?为什么我不能onDragCompleted
用来触发任何类型的音频播放器功能?
解决方案
推荐阅读
- android - 单击登录按钮时应用程序崩溃(简单登录注册测试)
- spring-boot - Spring thymeleaf 模板引擎找不到模板文件
- php - elFinder - 如何从 AWS S3 存储桶打开/显示特定文件夹
- jquery - Ajax 请求正常,但在错误响应文本中接收数据
- amazon-web-services - AWS ECS:如何在不使用 ALB 的情况下在 ECS 集群内的服务之间进行通信?有办法吗?
- go - 如何在 go 中 time.Parse() 逗号分隔毫秒
- html - 右上角的引导按钮
- python - 在梯度更新期间更新张量矩阵的特定行?
- java - HMACSHA256.ComputeHash(byte[] arr, int , int ) 与 Java Mac.doFinal(byte[] arr) 的输出不匹配
- javascript - 在赛普拉斯,我的餐桌数来不及评估