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

增加预估时间栏

上级 b6a651e9
......@@ -565,19 +565,30 @@ class _VideoPlayerPageState extends State<VideoPlayerPage> {
title: '切换视频source',
onTap: () {
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(
dataSource:
'https://mpv.videocc.net/8f38fa3352/0/8f38fa33525a64b20de46bb5271f5ba0_1.mp4',
'https://mpv.videocc.net/8f38fa3352/c/8f38fa3352029c8ac2af1c90e3bb7cdc_1.mp4',
title: 'LD',
),
VideoDefinitionItem(
dataSource:
'https://mpv.videocc.net/8f38fa3352/0/8f38fa33525a64b20de46bb5271f5ba0_2.mp4',
'https://mpv.videocc.net/8f38fa3352/c/8f38fa3352029c8ac2af1c90e3bb7cdc_2.mp4',
title: 'SD',
),
];
videoUrl =
'https://mpv.videocc.net/8f38fa3352/0/8f38fa33525a64b20de46bb5271f5ba0_1.mp4';
'https://mpv.videocc.net/8f38fa3352/c/8f38fa3352029c8ac2af1c90e3bb7cdc_1.mp4';
setState(() {});
},
),
......
......@@ -3,7 +3,6 @@ import 'dart:io';
import 'package:connectivity/connectivity.dart';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter/services.dart';
import 'package:gz_orientation/gz_orientation.dart';
import 'package:gz_video_player/video_definition.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_speed_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:screen_brightness/screen_brightness.dart';
import 'package:video_player/video_player.dart';
......@@ -142,6 +142,9 @@ class GZVideoPlayerState extends State<GZVideoPlayer>
/// 视频音量
final ValueNotifier<double> _volume = ValueNotifier(1.0);
/// 预估滑动时间
final EstimatedTimeNotifier _estimatedTimeNotifier = EstimatedTimeNotifier();
/// 是否显示控制拦
bool _showMenu = false;
......@@ -179,6 +182,9 @@ class GZVideoPlayerState extends State<GZVideoPlayer>
/// 视频比例
double _playerAspectRatio = 1.0;
dynamic _dataSource;
DataSourceType _sourceType = DataSourceType.network;
late StreamSubscription<ConnectivityResult> _subscription;
@override
......@@ -229,7 +235,6 @@ class GZVideoPlayerState extends State<GZVideoPlayer>
_initPlayer();
}
Future<void> initBrightness() async {
double brightness = await ScreenBrightness().current;
_brightness.value = brightness;
......@@ -266,6 +271,7 @@ class GZVideoPlayerState extends State<GZVideoPlayer>
_subscription.cancel();
_brightness.dispose();
_volume.dispose();
_estimatedTimeNotifier.dispose();
if (_originBrightness != null) {
ScreenBrightness().setScreenBrightness(_originBrightness!);
}
......@@ -309,6 +315,8 @@ class GZVideoPlayerState extends State<GZVideoPlayer>
required dynamic source,
VoidCallback? initializeCallback,
}) async {
_sourceType = type;
_dataSource = source;
VideoPlayerController tempController = _createVideoPlayerController(
type: type,
source: source,
......@@ -399,7 +407,7 @@ class GZVideoPlayerState extends State<GZVideoPlayer>
}
_isBuffing = _controller.value.isBuffering;
setState(() {});
// setState(() {});
}
}
......@@ -417,13 +425,15 @@ class GZVideoPlayerState extends State<GZVideoPlayer>
_controller.play();
_isEnded = false;
}
Future.delayed(const Duration(seconds: 1), () {
Future.delayed(const Duration(milliseconds: 1500), () {
_controller.setPlaybackSpeed(_speedItem.speed);
});
}
void _initPlayer() {
if (widget.dataSource == null || widget.dataSource == "") return;
_dataSource = widget.dataSource;
_sourceType = widget.sourceType;
_controller = _createVideoPlayerController(
source: widget.dataSource,
type: widget.sourceType,
......@@ -616,13 +626,23 @@ class GZVideoPlayerState extends State<GZVideoPlayer>
'progress': Expanded(
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 8),
child: VideoLinearProgressBar(_controller,
allowScrubbing: widget.playOptions.allowScrubbing,
onProgressDrag: widget.onProgressDrag,
padding:
widget.videoStyle.videoControlBarStyle.progressStyle.padding,
progressStyle:
widget.videoStyle.videoControlBarStyle.progressStyle),
child: VideoLinearProgressBar(
_controller,
allowScrubbing: widget.playOptions.allowScrubbing,
onProgressDrag: (Duration position, Duration duration) {
widget.onProgressDrag?.call(position, duration);
_estimatedTimeNotifier.update(
position: position,
duration: duration,
);
},
onDragEnd: () {
_estimatedTimeNotifier.dragEnd();
},
padding:
widget.videoStyle.videoControlBarStyle.progressStyle.padding,
progressStyle: widget.videoStyle.videoControlBarStyle.progressStyle,
),
),
),
......@@ -752,8 +772,8 @@ class GZVideoPlayerState extends State<GZVideoPlayer>
onTap: () {
_isEnded = false;
_updateDataSource(
source: widget.dataSource,
type: widget.sourceType,
source: _dataSource,
type: _sourceType,
);
},
child: widget.videoStyle.replayIcon,
......@@ -840,6 +860,9 @@ class GZVideoPlayerState extends State<GZVideoPlayer>
},
),
/// 预估时间栏
VideoEstimatedTimeBar(notifier: _estimatedTimeNotifier),
widget.brightnessWidget ??
BrightnessWidget(
brightness: _brightness,
......@@ -893,18 +916,33 @@ class GZVideoPlayerState extends State<GZVideoPlayer>
}
var currentPosition = _controller.value.position;
if (details.primaryDelta != null) {
_controller.seekTo(Duration(
milliseconds: details.primaryDelta! > 0
? currentPosition.inMilliseconds +
widget.playOptions.progressGestureUnit
: currentPosition.inMilliseconds -
widget.playOptions.progressGestureUnit));
late Duration position;
if (details.primaryDelta! > 0) {
int milliseconds = currentPosition.inMilliseconds +
widget.playOptions.progressGestureUnit;
milliseconds =
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) {
if (!_controller.value.isPlaying) {
_controller.play();
}
_estimatedTimeNotifier.dragEnd();
},
/// 垂直滑动 - 调节亮度以及音量
......
......@@ -14,6 +14,7 @@ class VideoLinearProgressBar extends StatefulWidget {
this.allowScrubbing,
this.padding = const EdgeInsets.only(top: 5.0),
this.onProgressDrag,
this.onDragEnd,
}) : progressStyle = progressStyle ?? VideoProgressStyle();
final VideoPlayerController controller;
......@@ -26,6 +27,8 @@ class VideoLinearProgressBar extends StatefulWidget {
final VideoProgressDragHandle? onProgressDrag;
final VoidCallback? onDragEnd;
@override
State<StatefulWidget> createState() => _VideoLinearProgressBarState();
}
......@@ -60,6 +63,7 @@ class _VideoLinearProgressBarState extends State<VideoLinearProgressBar> {
return _VideoScrubber(
controller: controller,
handleDrag: widget.onProgressDrag,
onDragEnd: widget.onDragEnd,
child: CustomPaint(
painter: _ProgressBarPainter(controller.value, style),
child: Container(),
......@@ -74,11 +78,13 @@ class _VideoScrubber extends StatefulWidget {
required this.child,
required this.controller,
this.handleDrag,
this.onDragEnd,
});
final Widget child;
final VideoPlayerController controller;
final VideoProgressDragHandle? handleDrag;
final VoidCallback? onDragEnd;
@override
_VideoScrubberState createState() => _VideoScrubberState();
......@@ -104,7 +110,13 @@ class _VideoScrubberState extends State<_VideoScrubber> {
final RenderBox box = context.findRenderObject() as RenderBox;
final Offset tapPos = box.globalToLocal(globalPosition);
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);
}
}
......@@ -132,6 +144,7 @@ class _VideoScrubberState extends State<_VideoScrubber> {
if (_controllerWasPlaying) {
// controller.play();
}
widget.onDragEnd?.call();
},
onTapDown: (TapDownDetails details) {
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 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论