cb38bc90
liangchengyou
feat:视频跟读逻辑处理
|
1
2
3
4
|
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:video_player/video_player.dart';
|
7d6a6ddc
liangchengyou
feat:1.0.1优化
|
5
|
import 'package:wow_english/models/read_content_entity.dart';
|
cb38bc90
liangchengyou
feat:视频跟读逻辑处理
|
6
7
8
9
|
import '../bloc/repeat_after_content_bloc.dart';
class RepeatVideoWidget extends StatefulWidget {
|
7d6a6ddc
liangchengyou
feat:1.0.1优化
|
10
|
const RepeatVideoWidget({super.key, this.videoUrl, required this.videoUrls});
|
cb38bc90
liangchengyou
feat:视频跟读逻辑处理
|
11
|
final String? videoUrl;
|
7d6a6ddc
liangchengyou
feat:1.0.1优化
|
12
|
final List<ReadContentEntity?> videoUrls;
|
cb38bc90
liangchengyou
feat:视频跟读逻辑处理
|
13
14
15
16
17
18
19
20
21
22
23
24
|
@override
State<StatefulWidget> createState() {
return _RepeatVideoWidgetState();
}
}
class _RepeatVideoWidgetState extends State<RepeatVideoWidget> {
VideoPlayerController? _controller;
String _currentTime = '00:00';
String _totalTime = '00:00';
double _playDegree = 0.5;
|
7d6a6ddc
liangchengyou
feat:1.0.1优化
|
25
|
int _currentPlayIndex = 0;
|
cb38bc90
liangchengyou
feat:视频跟读逻辑处理
|
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
|
String formatDuration(Duration duration) {
String minutes = duration.inMinutes.remainder(60).toString().padLeft(2, '0');
String seconds = duration.inSeconds.remainder(60).toString().padLeft(2, '0');
return "$minutes:$seconds";
}
void _addListener() {
_controller!.addListener(() {
if(_controller!.value.isInitialized) {
if (_controller!.value.isPlaying) {
setState(() {
double currentSecond = (_controller!.value.position.inMinutes.remainder(60)*60+_controller!.value.position.inSeconds.remainder(60)).toDouble();
int totalSecond = _controller!.value.duration.inMinutes.remainder(60)*60+_controller!.value.duration.inSeconds.remainder(60);
_currentTime = formatDuration(_controller!.value.position);
_playDegree = currentSecond/totalSecond;
if(_playDegree < 0) {
_playDegree = 0.0;
}
if(_playDegree > 1) {
_playDegree = 1.0;
}
});
}
}
});
}
@override
void initState() {
super.initState();
|
7d6a6ddc
liangchengyou
feat:1.0.1优化
|
58
59
60
61
62
|
var videoUrl = '';
if(widget.videoUrls.isNotEmpty) {
videoUrl = widget.videoUrls[_currentPlayIndex]?.videoUrl??'';
}
_initVideo(videoUrl);
|
cb38bc90
liangchengyou
feat:视频跟读逻辑处理
|
63
64
65
66
67
68
69
70
71
72
73
74
75
76
|
}
@override
Widget build(BuildContext context) {
return Center(
child: _controller!.value.isInitialized ? BlocListener<RepeatAfterContentBloc,RepeatAfterContentState>(
listener: (context, state){
if (state is VideoPlayChangeState) {
if (context.read<RepeatAfterContentBloc>().videoPlaying) {
_controller!.play();
} else {
_controller!.pause();
}
}
|
7d6a6ddc
liangchengyou
feat:1.0.1优化
|
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
|
if (state is ChangeVideoPlayIndexState) {
if(state.isNext) {
if (_currentPlayIndex != (widget.videoUrls.length-1)) {
_currentPlayIndex++;
_destroyVideo();
_initVideo(widget.videoUrls[_currentPlayIndex]!.videoUrl!);
}
} else {
if (_currentPlayIndex > 0) {
_currentPlayIndex--;
_destroyVideo();
_initVideo(widget.videoUrls[_currentPlayIndex]!.videoUrl!);
}
}
}
|
cb38bc90
liangchengyou
feat:视频跟读逻辑处理
|
93
94
95
96
97
98
99
100
101
102
103
104
|
},
child: SizedBox(
child: Column(
children: [
Expanded(
child: Stack(
children: [
Container(
width: double.infinity,
height: double.infinity,
alignment: Alignment.center,
decoration: BoxDecoration(
|
49787541
liangchengyou
feat:添加ios快速打包脚本
|
105
|
color: Colors.black,
|
cb38bc90
liangchengyou
feat:视频跟读逻辑处理
|
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
border: Border.all(
width: 1.0,
color: const Color(0xFF140C10),
),
borderRadius: BorderRadius.circular(5.r)
),
child: AspectRatio(
aspectRatio: _controller!.value.aspectRatio,
child: VideoPlayer(_controller!),
),
),
Positioned(
left: 0,
right: 0,
bottom: 0,
|
7d6a6ddc
liangchengyou
feat:1.0.1优化
|
121
122
123
124
|
child: LinearProgressIndicator(
color: const Color(0xFF78B72D),
backgroundColor: const Color(0xFF7E756C),
value: _playDegree,
|
cb38bc90
liangchengyou
feat:视频跟读逻辑处理
|
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
|
))
],
),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(_currentTime),
Text(_totalTime),
],
)
],
),
)
)
:
Container(
color: Colors.white,
|
66a7e3e7
吴启风
feat:退出课堂和结束课堂优化
|
143
144
145
146
147
148
149
150
|
child: const CircularProgressIndicator(),
// Text(
// '视频加载中....',
// style: TextStyle(
// fontSize: 20.sp,
// color: Colors.black
// ),
// ),
|
cb38bc90
liangchengyou
feat:视频跟读逻辑处理
|
151
152
153
154
|
),
);
}
|
7d6a6ddc
liangchengyou
feat:1.0.1优化
|
155
|
void _initVideo(String videoUrl) {
|
934e2b47
liangchengyou
feat:权限调整+课程进度接口对接
|
156
157
158
159
160
161
162
163
164
165
166
167
|
if(videoUrl.isNotEmpty) {
Uri uri = Uri.parse(videoUrl);
_controller = VideoPlayerController.networkUrl(uri)
..initialize().then((_){
setState(() {
_currentTime = formatDuration(_controller!.value.position);
_totalTime = formatDuration(_controller!.value.duration);
_controller!.setLooping(false);
_controller!.setVolume(100);
_controller!.play();
});
_addListener();
|
7d6a6ddc
liangchengyou
feat:1.0.1优化
|
168
|
});
|
934e2b47
liangchengyou
feat:权限调整+课程进度接口对接
|
169
|
}
|
7d6a6ddc
liangchengyou
feat:1.0.1优化
|
170
171
172
|
}
void _destroyVideo() {
|
cb38bc90
liangchengyou
feat:视频跟读逻辑处理
|
173
174
|
_controller?.dispose();
_controller?.removeListener(() {});
|
7d6a6ddc
liangchengyou
feat:1.0.1优化
|
175
176
177
178
179
|
}
@override
void dispose() {
_destroyVideo();
|
cb38bc90
liangchengyou
feat:视频跟读逻辑处理
|
180
181
182
|
super.dispose();
}
}
|