首页 > 解决方案 > 在聊天中播放多个音频对象

问题描述

在下面的 ListView(这是一个包含文本、图像和文档对象的聊天)中,我将音频列表作为小部件(下图是一个示例),当我按下播放键时,两者都会播放。我怎样才能让它一次只播放一个?是否可以将其创建为多个独立的对象,而无需进行安排?任何建议。 在此处输入图像描述

just_audio:^0.7.4 audio_video_progress_bar:^0.3.1

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  late final PageManager _pageManager;
  int value = 2;

  _addItem() {
    setState(() {
      value = value + 1;
    });
  }

  @override
  void initState() {
    super.initState();
    //_addItem();
    _pageManager = PageManager();
  }

  @override
  void dispose() {
    _pageManager.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: ListView.builder(
            itemCount: this.value,
            itemBuilder: (context, index) => this.burbuja()),
        floatingActionButton: FloatingActionButton(
          onPressed: _addItem,
          child: Icon(Icons.add),
        ),
      ),
    );
  }

  Widget burbuja() {
    return new Material(
        child: new Container(
      //'tipo' == 3; esto para los que son audio mensaje
      child: Row(
        //mainAxisAlignment: MainAxisAlignment.start,
        mainAxisSize: MainAxisSize.max,
        children: [
          //Spacer(),
          ValueListenableBuilder<ButtonState>(
            valueListenable: _pageManager.buttonNotifier,
            builder: (_, value, __) {
              switch (value) {
                case ButtonState.loading:
                  return Container(
                    margin: EdgeInsets.all(10.0),
                    width: 32.0,
                    height: 32.0,
                    child: CircularProgressIndicator(),
                  );
                case ButtonState.paused:
                  return IconButton(
                    icon: Icon(Icons.play_arrow),
                    iconSize: 32.0,
                    onPressed: _pageManager.play,
                  );
                case ButtonState.playing:
                  return IconButton(
                    icon: Icon(Icons.pause),
                    iconSize: 32.0,
                    onPressed: _pageManager.pause,
                  );
              }
            },
          ),
          Container(
            //'tipo' == 3; esto para los que son audio mensaje
            child: ValueListenableBuilder<ProgressBarState>(
              valueListenable: _pageManager.progressNotifier,
              builder: (_, value, __) {
                return ProgressBar(
                  progress: value.current,
                  buffered: value.buffered,
                  total: value.total,
                  onSeek: _pageManager.seek,
                );
              },
            ),
            padding: EdgeInsets.fromLTRB(15.0, 10.0, 5.0, 5.0),
            width: 200.0,
            /*       decoration: BoxDecoration(
                      color: Color(Constants.COLOR_PRIMARY),
                      borderRadius: BorderRadius.circular(8.0)),
                  margin: EdgeInsets.only(
                      bottom: isLastMessageRight(index) ? 20.0 : 10.0,
                      right: 10.0), */
          ),
        ],
      ),
      padding: EdgeInsets.fromLTRB(15.0, 10.0, 5.0, 5.0),
      width: 3500.0,
      decoration: BoxDecoration(
          color: Colors.amberAccent, borderRadius: BorderRadius.circular(8.0)),
      margin: EdgeInsets.only(bottom: 10.0, right: 10.0),
    ));
  }
}

//文件页面管理器

import 'package:flutter/material.dart';
import 'package:just_audio/just_audio.dart';

class PageManager {
  final progressNotifier = ValueNotifier<ProgressBarState>(
    ProgressBarState(
      current: Duration.zero,
      buffered: Duration.zero,
      total: Duration.zero,
    ),
  );
  final buttonNotifier = ValueNotifier<ButtonState>(ButtonState.paused);

  late AudioPlayer _audioPlayer;
  static const url =
      'https://www.soundhelix.com/examples/mp3/SoundHelix-Song-2.mp3';

  PageManager() {
    _init();
  }

  void _init() async {
    // initialize the song
    _audioPlayer = AudioPlayer();
    await _audioPlayer.setUrl(url);

    // listen for changes in player state
    _audioPlayer.playerStateStream.listen((playerState) {
      final isPlaying = playerState.playing;
      final processingState = playerState.processingState;
      if (processingState == ProcessingState.loading ||
          processingState == ProcessingState.buffering) {
        buttonNotifier.value = ButtonState.loading;
      } else if (!isPlaying) {
        buttonNotifier.value = ButtonState.paused;
      } else if (processingState != ProcessingState.completed) {
        buttonNotifier.value = ButtonState.playing;
      } else {
        _audioPlayer.seek(Duration.zero);
        _audioPlayer.pause();
      }
    });

    // listen for changes in play position
    _audioPlayer.positionStream.listen((position) {
      final oldState = progressNotifier.value;
      progressNotifier.value = ProgressBarState(
        current: position,
        buffered: oldState.buffered,
        total: oldState.total,
      );
    });

    // listen for changes in the buffered position
    _audioPlayer.bufferedPositionStream.listen((bufferedPosition) {
      final oldState = progressNotifier.value;
      progressNotifier.value = ProgressBarState(
        current: oldState.current,
        buffered: bufferedPosition,
        total: oldState.total,
      );
    });

    // listen for changes in the total audio duration
    _audioPlayer.durationStream.listen((totalDuration) {
      final oldState = progressNotifier.value;
      progressNotifier.value = ProgressBarState(
        current: oldState.current,
        buffered: oldState.buffered,
        total: totalDuration ?? Duration.zero,
      );
    });
  }

  void play() async {
    _audioPlayer.play();
  }

  void pause() {
    _audioPlayer.pause();
  }

  void seek(Duration position) {
    _audioPlayer.seek(position);
  }

  void dispose() {
    _audioPlayer.dispose();
  }
}

class ProgressBarState {
  ProgressBarState({
    required this.current,
    required this.buffered,
    required this.total,
  });
  final Duration current;
  final Duration buffered;
  final Duration total;
}

enum ButtonState { paused, playing, loading }

标签: firebaseflutterdart

解决方案


看起来屏幕截图中的不同音频播放器具有相同的音频文件。因此,当您运行时AudioPlayer.play,它会在两种情况下播放音频。

您可以设置多个音频源并播放您想要的确切音频文件。

以下是文档中用于设置多个音频源的示例方法:

await player.setAudioSource(
  ConcatenatingAudioSource(
    // Start loading next item just before reaching it.
    useLazyPreparation: true, // default
    // Customise the shuffle algorithm.
    shuffleOrder: DefaultShuffleOrder(), // default
    // Specify the items in the playlist.
    children: [
      AudioSource.uri(Uri.parse("https://example.com/track1.mp3")),
      AudioSource.uri(Uri.parse("https://example.com/track2.mp3")),
      AudioSource.uri(Uri.parse("https://example.com/track3.mp3")),
    ],
  ),
  // Playback will be prepared to start from track1.mp3
  initialIndex: 0, // default
  // Playback will be prepared to start from position zero.
  initialPosition: Duration.zero, // default
);

如果您知道索引,则可以通过查找确切的索引然后像正常一样播放它来播放特定文件。

player.seek(Duration.zero, index: index);
player.play()

推荐阅读