提交 0d7e0527 authored 作者: jungleiOS's avatar jungleiOS

增加预估时间栏

上级 b6a651e9
...@@ -565,19 +565,30 @@ class _VideoPlayerPageState extends State<VideoPlayerPage> { ...@@ -565,19 +565,30 @@ class _VideoPlayerPageState extends State<VideoPlayerPage> {
title: '切换视频source', title: '切换视频source',
onTap: () { onTap: () {
definitionList = [ definitionList = [
// VideoDefinitionItem(
// dataSource:
// 'https://mpv.videocc.net/8f38fa3352/0/8f38fa33525a64b20de46bb5271f5ba0_1.mp4',
// title: 'LD',
// ),
// VideoDefinitionItem(
// dataSource:
// 'https://mpv.videocc.net/8f38fa3352/0/8f38fa33525a64b20de46bb5271f5ba0_2.mp4',
// title: 'SD',
// ),
// "play_url": "https://mpv.videocc.net/8f38fa3352/c/8f38fa3352029c8ac2af1c90e3bb7cdc_2.mp4",
VideoDefinitionItem( VideoDefinitionItem(
dataSource: dataSource:
'https://mpv.videocc.net/8f38fa3352/0/8f38fa33525a64b20de46bb5271f5ba0_1.mp4', 'https://mpv.videocc.net/8f38fa3352/c/8f38fa3352029c8ac2af1c90e3bb7cdc_1.mp4',
title: 'LD', title: 'LD',
), ),
VideoDefinitionItem( VideoDefinitionItem(
dataSource: dataSource:
'https://mpv.videocc.net/8f38fa3352/0/8f38fa33525a64b20de46bb5271f5ba0_2.mp4', 'https://mpv.videocc.net/8f38fa3352/c/8f38fa3352029c8ac2af1c90e3bb7cdc_2.mp4',
title: 'SD', title: 'SD',
), ),
]; ];
videoUrl = videoUrl =
'https://mpv.videocc.net/8f38fa3352/0/8f38fa33525a64b20de46bb5271f5ba0_1.mp4'; 'https://mpv.videocc.net/8f38fa3352/c/8f38fa3352029c8ac2af1c90e3bb7cdc_1.mp4';
setState(() {}); setState(() {});
}, },
), ),
......
...@@ -3,7 +3,6 @@ import 'dart:io'; ...@@ -3,7 +3,6 @@ import 'dart:io';
import 'package:connectivity/connectivity.dart'; import 'package:connectivity/connectivity.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:gz_orientation/gz_orientation.dart'; import 'package:gz_orientation/gz_orientation.dart';
import 'package:gz_video_player/video_definition.dart'; import 'package:gz_video_player/video_definition.dart';
...@@ -18,6 +17,7 @@ import 'package:gz_video_player/widget/video_definition_side_bar.dart'; ...@@ -18,6 +17,7 @@ import 'package:gz_video_player/widget/video_definition_side_bar.dart';
import 'package:gz_video_player/widget/video_loading_view.dart'; import 'package:gz_video_player/widget/video_loading_view.dart';
import 'package:gz_video_player/widget/video_speed_bar.dart'; import 'package:gz_video_player/widget/video_speed_bar.dart';
import 'package:gz_video_player/widget/video_top_bar.dart'; import 'package:gz_video_player/widget/video_top_bar.dart';
import 'package:gz_video_player/widget/vidoe_estimated_time_bar.dart';
import 'package:gz_video_player/widget/volume.dart'; import 'package:gz_video_player/widget/volume.dart';
import 'package:screen_brightness/screen_brightness.dart'; import 'package:screen_brightness/screen_brightness.dart';
import 'package:video_player/video_player.dart'; import 'package:video_player/video_player.dart';
...@@ -142,6 +142,9 @@ class GZVideoPlayerState extends State<GZVideoPlayer> ...@@ -142,6 +142,9 @@ class GZVideoPlayerState extends State<GZVideoPlayer>
/// 视频音量 /// 视频音量
final ValueNotifier<double> _volume = ValueNotifier(1.0); final ValueNotifier<double> _volume = ValueNotifier(1.0);
/// 预估滑动时间
final EstimatedTimeNotifier _estimatedTimeNotifier = EstimatedTimeNotifier();
/// 是否显示控制拦 /// 是否显示控制拦
bool _showMenu = false; bool _showMenu = false;
...@@ -179,6 +182,9 @@ class GZVideoPlayerState extends State<GZVideoPlayer> ...@@ -179,6 +182,9 @@ class GZVideoPlayerState extends State<GZVideoPlayer>
/// 视频比例 /// 视频比例
double _playerAspectRatio = 1.0; double _playerAspectRatio = 1.0;
dynamic _dataSource;
DataSourceType _sourceType = DataSourceType.network;
late StreamSubscription<ConnectivityResult> _subscription; late StreamSubscription<ConnectivityResult> _subscription;
@override @override
...@@ -229,7 +235,6 @@ class GZVideoPlayerState extends State<GZVideoPlayer> ...@@ -229,7 +235,6 @@ class GZVideoPlayerState extends State<GZVideoPlayer>
_initPlayer(); _initPlayer();
} }
Future<void> initBrightness() async { Future<void> initBrightness() async {
double brightness = await ScreenBrightness().current; double brightness = await ScreenBrightness().current;
_brightness.value = brightness; _brightness.value = brightness;
...@@ -266,6 +271,7 @@ class GZVideoPlayerState extends State<GZVideoPlayer> ...@@ -266,6 +271,7 @@ class GZVideoPlayerState extends State<GZVideoPlayer>
_subscription.cancel(); _subscription.cancel();
_brightness.dispose(); _brightness.dispose();
_volume.dispose(); _volume.dispose();
_estimatedTimeNotifier.dispose();
if (_originBrightness != null) { if (_originBrightness != null) {
ScreenBrightness().setScreenBrightness(_originBrightness!); ScreenBrightness().setScreenBrightness(_originBrightness!);
} }
...@@ -309,6 +315,8 @@ class GZVideoPlayerState extends State<GZVideoPlayer> ...@@ -309,6 +315,8 @@ class GZVideoPlayerState extends State<GZVideoPlayer>
required dynamic source, required dynamic source,
VoidCallback? initializeCallback, VoidCallback? initializeCallback,
}) async { }) async {
_sourceType = type;
_dataSource = source;
VideoPlayerController tempController = _createVideoPlayerController( VideoPlayerController tempController = _createVideoPlayerController(
type: type, type: type,
source: source, source: source,
...@@ -399,7 +407,7 @@ class GZVideoPlayerState extends State<GZVideoPlayer> ...@@ -399,7 +407,7 @@ class GZVideoPlayerState extends State<GZVideoPlayer>
} }
_isBuffing = _controller.value.isBuffering; _isBuffing = _controller.value.isBuffering;
setState(() {}); // setState(() {});
} }
} }
...@@ -417,13 +425,15 @@ class GZVideoPlayerState extends State<GZVideoPlayer> ...@@ -417,13 +425,15 @@ class GZVideoPlayerState extends State<GZVideoPlayer>
_controller.play(); _controller.play();
_isEnded = false; _isEnded = false;
} }
Future.delayed(const Duration(seconds: 1), () { Future.delayed(const Duration(milliseconds: 1500), () {
_controller.setPlaybackSpeed(_speedItem.speed); _controller.setPlaybackSpeed(_speedItem.speed);
}); });
} }
void _initPlayer() { void _initPlayer() {
if (widget.dataSource == null || widget.dataSource == "") return; if (widget.dataSource == null || widget.dataSource == "") return;
_dataSource = widget.dataSource;
_sourceType = widget.sourceType;
_controller = _createVideoPlayerController( _controller = _createVideoPlayerController(
source: widget.dataSource, source: widget.dataSource,
type: widget.sourceType, type: widget.sourceType,
...@@ -616,13 +626,23 @@ class GZVideoPlayerState extends State<GZVideoPlayer> ...@@ -616,13 +626,23 @@ class GZVideoPlayerState extends State<GZVideoPlayer>
'progress': Expanded( 'progress': Expanded(
child: Container( child: Container(
padding: const EdgeInsets.symmetric(horizontal: 8), padding: const EdgeInsets.symmetric(horizontal: 8),
child: VideoLinearProgressBar(_controller, child: VideoLinearProgressBar(
_controller,
allowScrubbing: widget.playOptions.allowScrubbing, allowScrubbing: widget.playOptions.allowScrubbing,
onProgressDrag: widget.onProgressDrag, onProgressDrag: (Duration position, Duration duration) {
widget.onProgressDrag?.call(position, duration);
_estimatedTimeNotifier.update(
position: position,
duration: duration,
);
},
onDragEnd: () {
_estimatedTimeNotifier.dragEnd();
},
padding: padding:
widget.videoStyle.videoControlBarStyle.progressStyle.padding, widget.videoStyle.videoControlBarStyle.progressStyle.padding,
progressStyle: progressStyle: widget.videoStyle.videoControlBarStyle.progressStyle,
widget.videoStyle.videoControlBarStyle.progressStyle), ),
), ),
), ),
...@@ -752,8 +772,8 @@ class GZVideoPlayerState extends State<GZVideoPlayer> ...@@ -752,8 +772,8 @@ class GZVideoPlayerState extends State<GZVideoPlayer>
onTap: () { onTap: () {
_isEnded = false; _isEnded = false;
_updateDataSource( _updateDataSource(
source: widget.dataSource, source: _dataSource,
type: widget.sourceType, type: _sourceType,
); );
}, },
child: widget.videoStyle.replayIcon, child: widget.videoStyle.replayIcon,
...@@ -840,6 +860,9 @@ class GZVideoPlayerState extends State<GZVideoPlayer> ...@@ -840,6 +860,9 @@ class GZVideoPlayerState extends State<GZVideoPlayer>
}, },
), ),
/// 预估时间栏
VideoEstimatedTimeBar(notifier: _estimatedTimeNotifier),
widget.brightnessWidget ?? widget.brightnessWidget ??
BrightnessWidget( BrightnessWidget(
brightness: _brightness, brightness: _brightness,
...@@ -893,18 +916,33 @@ class GZVideoPlayerState extends State<GZVideoPlayer> ...@@ -893,18 +916,33 @@ class GZVideoPlayerState extends State<GZVideoPlayer>
} }
var currentPosition = _controller.value.position; var currentPosition = _controller.value.position;
if (details.primaryDelta != null) { if (details.primaryDelta != null) {
_controller.seekTo(Duration( late Duration position;
milliseconds: details.primaryDelta! > 0 if (details.primaryDelta! > 0) {
? currentPosition.inMilliseconds + int milliseconds = currentPosition.inMilliseconds +
widget.playOptions.progressGestureUnit widget.playOptions.progressGestureUnit;
: currentPosition.inMilliseconds - milliseconds =
widget.playOptions.progressGestureUnit)); milliseconds > _controller.value.duration.inMilliseconds
? _controller.value.duration.inMilliseconds
: milliseconds;
position = Duration(milliseconds: milliseconds);
} else {
int milliseconds = currentPosition.inMilliseconds -
widget.playOptions.progressGestureUnit;
milliseconds = milliseconds < 0 ? 0 : milliseconds;
position = Duration(milliseconds: milliseconds);
}
_controller.seekTo(position);
_estimatedTimeNotifier.update(
position: position,
duration: _controller.value.duration,
);
} }
}, },
onHorizontalDragEnd: (DragEndDetails details) { onHorizontalDragEnd: (DragEndDetails details) {
if (!_controller.value.isPlaying) { if (!_controller.value.isPlaying) {
_controller.play(); _controller.play();
} }
_estimatedTimeNotifier.dragEnd();
}, },
/// 垂直滑动 - 调节亮度以及音量 /// 垂直滑动 - 调节亮度以及音量
......
...@@ -14,6 +14,7 @@ class VideoLinearProgressBar extends StatefulWidget { ...@@ -14,6 +14,7 @@ class VideoLinearProgressBar extends StatefulWidget {
this.allowScrubbing, this.allowScrubbing,
this.padding = const EdgeInsets.only(top: 5.0), this.padding = const EdgeInsets.only(top: 5.0),
this.onProgressDrag, this.onProgressDrag,
this.onDragEnd,
}) : progressStyle = progressStyle ?? VideoProgressStyle(); }) : progressStyle = progressStyle ?? VideoProgressStyle();
final VideoPlayerController controller; final VideoPlayerController controller;
...@@ -26,6 +27,8 @@ class VideoLinearProgressBar extends StatefulWidget { ...@@ -26,6 +27,8 @@ class VideoLinearProgressBar extends StatefulWidget {
final VideoProgressDragHandle? onProgressDrag; final VideoProgressDragHandle? onProgressDrag;
final VoidCallback? onDragEnd;
@override @override
State<StatefulWidget> createState() => _VideoLinearProgressBarState(); State<StatefulWidget> createState() => _VideoLinearProgressBarState();
} }
...@@ -60,6 +63,7 @@ class _VideoLinearProgressBarState extends State<VideoLinearProgressBar> { ...@@ -60,6 +63,7 @@ class _VideoLinearProgressBarState extends State<VideoLinearProgressBar> {
return _VideoScrubber( return _VideoScrubber(
controller: controller, controller: controller,
handleDrag: widget.onProgressDrag, handleDrag: widget.onProgressDrag,
onDragEnd: widget.onDragEnd,
child: CustomPaint( child: CustomPaint(
painter: _ProgressBarPainter(controller.value, style), painter: _ProgressBarPainter(controller.value, style),
child: Container(), child: Container(),
...@@ -74,11 +78,13 @@ class _VideoScrubber extends StatefulWidget { ...@@ -74,11 +78,13 @@ class _VideoScrubber extends StatefulWidget {
required this.child, required this.child,
required this.controller, required this.controller,
this.handleDrag, this.handleDrag,
this.onDragEnd,
}); });
final Widget child; final Widget child;
final VideoPlayerController controller; final VideoPlayerController controller;
final VideoProgressDragHandle? handleDrag; final VideoProgressDragHandle? handleDrag;
final VoidCallback? onDragEnd;
@override @override
_VideoScrubberState createState() => _VideoScrubberState(); _VideoScrubberState createState() => _VideoScrubberState();
...@@ -104,7 +110,13 @@ class _VideoScrubberState extends State<_VideoScrubber> { ...@@ -104,7 +110,13 @@ class _VideoScrubberState extends State<_VideoScrubber> {
final RenderBox box = context.findRenderObject() as RenderBox; final RenderBox box = context.findRenderObject() as RenderBox;
final Offset tapPos = box.globalToLocal(globalPosition); final Offset tapPos = box.globalToLocal(globalPosition);
final double relative = tapPos.dx / box.size.width; final double relative = tapPos.dx / box.size.width;
final Duration position = controller.value.duration * relative; Duration position = controller.value.duration * relative;
if (position.inSeconds < 0) {
position = const Duration(seconds: 0);
}
if (position.inSeconds > controller.value.duration.inSeconds) {
position = controller.value.duration;
}
widget.handleDrag?.call(position, controller.value.duration); widget.handleDrag?.call(position, controller.value.duration);
} }
} }
...@@ -132,6 +144,7 @@ class _VideoScrubberState extends State<_VideoScrubber> { ...@@ -132,6 +144,7 @@ class _VideoScrubberState extends State<_VideoScrubber> {
if (_controllerWasPlaying) { if (_controllerWasPlaying) {
// controller.play(); // controller.play();
} }
widget.onDragEnd?.call();
}, },
onTapDown: (TapDownDetails details) { onTapDown: (TapDownDetails details) {
if (!controller.value.isInitialized) { if (!controller.value.isInitialized) {
......
import 'package:flutter/material.dart';
class VideoEstimatedTimeBar extends StatefulWidget {
const VideoEstimatedTimeBar({super.key, required this.notifier});
final EstimatedTimeNotifier notifier;
@override
State<VideoEstimatedTimeBar> createState() => _VideoEstimatedTimeBarState();
}
class _VideoEstimatedTimeBarState extends State<VideoEstimatedTimeBar> {
EstimatedTimeNotifier get notifier => widget.notifier;
String _position = '--:--';
String _duration = '--:--';
bool _hidden = true;
@override
void initState() {
super.initState();
notifier.addListener(_listener);
}
@override
Widget build(BuildContext context) {
return Offstage(
offstage: _hidden,
child: Align(
alignment: Alignment.center,
child: Container(
decoration: BoxDecoration(
color: Colors.black.withOpacity(0.5),
borderRadius: const BorderRadius.all(Radius.circular(6.0)),
),
padding: const EdgeInsets.all(8.0),
child: Text(
'$_position / $_duration',
style: const TextStyle(
color: Colors.white,
),
),
),
),
);
}
void _listener() {
if (notifier.duration.inHours == 0) {
var strPosition = notifier.position.toString().split('.')[0];
var strDuration = notifier.duration.toString().split('.')[0];
_position = "${strPosition.split(':')[1]}:${strPosition.split(':')[2]}";
_duration = "${strDuration.split(':')[1]}:${strDuration.split(':')[2]}";
} else {
_position = notifier.position.toString().split('.')[0];
_duration = notifier.duration.toString().split('.')[0];
}
_hidden = notifier.isEnd;
setState(() {});
}
@override
void dispose() {
notifier.removeListener(_listener);
super.dispose();
}
}
class EstimatedTimeNotifier with ChangeNotifier {
Duration _position = const Duration(seconds: 0);
Duration _duration = const Duration(seconds: 0);
bool _isEnd = true;
Duration get position => _position;
Duration get duration => _duration;
bool get isEnd => _isEnd;
void update({required Duration position, required Duration duration}) {
_position = position;
_duration = duration;
_isEnd = false;
notifyListeners();
}
void dragEnd() {
_isEnd = true;
notifyListeners();
}
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论