首页 > 解决方案 > 为什么 Flutter 的 Xlider Range Slider 上的 Handler 在我拖动它们后总是弹回?

问题描述

我正在尝试使用 Xlider 来控制 Flutter 的Audioplayers插件。但是每次我尝试在 Flutter 的XliderRange 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用来触发任何类型的音频播放器功能?

标签: flutterdartslideraudio-player

解决方案


推荐阅读