firebase - 在聊天中播放多个音频对象
问题描述
在下面的 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 }
解决方案
看起来屏幕截图中的不同音频播放器具有相同的音频文件。因此,当您运行时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()
推荐阅读
- react-native - 如何在 react-native 的嵌套映射函数中使用 if else 条件?
- prometheus - Prometheus 未从 file_sd_configs 读取黑盒目标
- ruby-on-rails - 从 has_many 检索记录:通过关系,包括连接模型列并给定约束?
- ios - 没有从 instamojo API 中获得价值
- c++ - 12小时到24小时时间转换
- javascript - 指定一个 React 组件作为另一个组件的 defaultProp
- multithreading - Rayon 会避免为少量工作生成线程吗?
- node.js - ng serve --proxy-config proxyconfig.json 不工作
- sql-server - INSERT 语句与 CHECK 约束冲突(插入表问题)
- django - 在 Django 中显示与登录用户相关的数据