5
5
import 'dart:async' ;
6
6
7
7
import 'package:flutter/material.dart' ;
8
- import 'package:assets_audio_player/assets_audio_player .dart' ;
8
+ import 'package:video_player/video_player .dart' ;
9
9
10
10
import 'package:wechat_assets_picker/src/constants/constants.dart' ;
11
11
import 'package:wechat_assets_picker/wechat_assets_picker.dart' ;
@@ -22,34 +22,39 @@ class AudioPageBuilder extends StatefulWidget {
22
22
final AssetEntity asset;
23
23
24
24
/// [State] for asset picker viewer.
25
- /// 资源查看器的状态[State]
25
+ /// 资源查看器的状态 [State]
26
26
final AssetPickerViewerState state;
27
27
28
28
@override
29
29
State <StatefulWidget > createState () => _AudioPageBuilderState ();
30
30
}
31
31
32
32
class _AudioPageBuilderState extends State <AudioPageBuilder > {
33
- /// Create an [AssetsAudioPlayer] instance for the page builder state.
34
- /// 创建一个[AssetsAudioPlayer] 的实例
35
- final AssetsAudioPlayer audioPlayer = AssetsAudioPlayer ();
33
+ /// A [StreamController] for current position of the [_controller] .
34
+ /// 控制器当前的播放进度
35
+ final StreamController <Duration > durationStreamController =
36
+ StreamController <Duration >.broadcast ();
37
+
38
+ /// Create a [VideoPlayerController] instance for the page builder state.
39
+ /// 创建一个 [VideoPlayerController] 的实例
40
+ VideoPlayerController _controller;
36
41
37
42
/// Whether the audio loaded.
38
43
/// 音频是否已经加载完成
39
44
bool isLoaded = false ;
40
45
41
- /// Whether there's some error when loading the audio.
42
- /// 加载音频时是否有错误
43
- bool isError = false ;
46
+ /// Whether the player is playing.
47
+ /// 播放器是否在播放
48
+ bool isPlaying = false ;
49
+
50
+ /// Whether the controller is playing.
51
+ /// 播放控制器是否在播放
52
+ bool get isControllerPlaying => _controller? .value? .isPlaying ?? false ;
44
53
45
54
/// Duration of the audio.
46
55
/// 音频的时长
47
56
Duration assetDuration;
48
57
49
- /// Audio instance.
50
- /// 音频实例
51
- Audio audio;
52
-
53
58
@override
54
59
void initState () {
55
60
super .initState ();
@@ -61,22 +66,23 @@ class _AudioPageBuilderState extends State<AudioPageBuilder> {
61
66
/// Stop and dispose player instance to stop playing
62
67
/// when dispose (e.g. page switched).
63
68
/// 状态销毁时停止并销毁实例(例如页面切换时)
64
- audioPlayer
65
- .. stop ()
66
- . .dispose ();
69
+ _controller ? . pause ();
70
+ _controller ? . removeListener (audioPlayerListener);
71
+ _controller ? .dispose ();
67
72
super .dispose ();
68
73
}
69
74
70
- /// Using [audioPlayer] to load content url from the asset.
71
- /// 使用 [audioPlayer] 通过content地址加载资源
75
+ /// Load content url from the asset.
76
+ /// 通过content地址加载资源
72
77
Future <void > openAudioFile () async {
73
78
try {
74
- assetDuration = Duration (seconds: widget.asset.duration);
75
- audio = Audio .file (await widget.asset.getMediaUrl ());
76
- audioPlayer.open (audio, autoStart: false );
79
+ final String url = await widget.asset.getMediaUrl ();
80
+ assetDuration = widget.asset.duration.seconds;
81
+ _controller = VideoPlayerController .network (url);
82
+ await _controller.initialize ();
83
+ _controller.addListener (audioPlayerListener);
77
84
} catch (e) {
78
85
realDebugPrint ('Error when opening audio file: $e ' );
79
- isError = true ;
80
86
} finally {
81
87
isLoaded = true ;
82
88
if (mounted) {
@@ -85,6 +91,22 @@ class _AudioPageBuilderState extends State<AudioPageBuilder> {
85
91
}
86
92
}
87
93
94
+ /// Listener for the player.
95
+ /// 播放器的监听方法
96
+ void audioPlayerListener () {
97
+ if (isControllerPlaying != isPlaying) {
98
+ isPlaying = isControllerPlaying;
99
+ if (mounted) {
100
+ setState (() {});
101
+ }
102
+ }
103
+
104
+ /// Add the current position into the stream.
105
+ if (_controller? .value? .position != null ) {
106
+ durationStreamController.add (_controller.value.position);
107
+ }
108
+ }
109
+
88
110
/// Title widget.
89
111
/// 标题组件
90
112
Widget get titleWidget => Text (
@@ -97,41 +119,32 @@ class _AudioPageBuilderState extends State<AudioPageBuilder> {
97
119
98
120
/// Button to control audio play/pause.
99
121
/// 控制音频播放或暂停的按钮
100
- Widget get audioControlButton => StreamBuilder <bool >(
101
- initialData: false ,
102
- stream: audioPlayer.isPlaying,
103
- builder: (BuildContext _, AsyncSnapshot <bool > data) {
104
- final bool isPlaying = data.data;
105
- return GestureDetector (
106
- onTap: () {
107
- if (isPlaying) {
108
- audioPlayer.pause ();
109
- } else {
110
- audioPlayer.play ();
111
- }
112
- },
113
- child: Container (
114
- margin: const EdgeInsets .all (20.0 ),
115
- decoration: BoxDecoration (
116
- boxShadow: < BoxShadow > [BoxShadow (color: Colors .black12)],
117
- shape: BoxShape .circle,
118
- ),
119
- child: Icon (
120
- isPlaying
121
- ? Icons .pause_circle_outline
122
- : Icons .play_circle_filled,
123
- size: 70.0 ,
124
- ),
125
- ),
126
- );
122
+ Widget get audioControlButton => GestureDetector (
123
+ onTap: () {
124
+ if (isPlaying) {
125
+ _controller.pause ();
126
+ } else {
127
+ _controller.play ();
128
+ }
127
129
},
130
+ child: Container (
131
+ margin: const EdgeInsets .all (20.0 ),
132
+ decoration: BoxDecoration (
133
+ boxShadow: < BoxShadow > [BoxShadow (color: Colors .black12)],
134
+ shape: BoxShape .circle,
135
+ ),
136
+ child: Icon (
137
+ isPlaying ? Icons .pause_circle_outline : Icons .play_circle_filled,
138
+ size: 70.0 ,
139
+ ),
140
+ ),
128
141
);
129
142
130
143
/// Duration indicator for the audio.
131
144
/// 音频的时长指示器
132
145
Widget get durationIndicator => StreamBuilder <Duration >(
133
146
initialData: Duration .zero,
134
- stream: audioPlayer.currentPosition ,
147
+ stream: durationStreamController.stream ,
135
148
builder: (BuildContext _, AsyncSnapshot <Duration > data) {
136
149
return Text (
137
150
'${Constants .textDelegate .durationIndicatorBuilder (data .data )}'
@@ -150,17 +163,13 @@ class _AudioPageBuilderState extends State<AudioPageBuilder> {
150
163
return ColoredBox (
151
164
color: context.themeData.backgroundColor,
152
165
child: isLoaded
153
- ? AudioWidget (
154
- audio: audio,
155
- play: audioPlayer.isPlaying.value,
156
- child: Column (
157
- mainAxisAlignment: MainAxisAlignment .center,
158
- children: < Widget > [
159
- titleWidget,
160
- audioControlButton,
161
- durationIndicator,
162
- ],
163
- ),
166
+ ? Column (
167
+ mainAxisAlignment: MainAxisAlignment .center,
168
+ children: < Widget > [
169
+ titleWidget,
170
+ audioControlButton,
171
+ durationIndicator,
172
+ ],
164
173
)
165
174
: const SizedBox .shrink (),
166
175
);
0 commit comments