提交 fbfc666b authored 作者: jungleiOS's avatar jungleiOS

修复播放器拖动后偶现页面音视频不同步问题 多播放器实例允许不恢复树屏

上级 7a7e465d
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:gz_video_player/video.dart';
import 'package:gz_video_player/video_control_bar_style.dart';
......@@ -9,6 +10,7 @@ import 'package:gz_video_player/video_speed.dart';
import 'package:gz_video_player/video_style.dart';
import 'package:gz_video_player/video_subtitles.dart';
import 'package:gz_video_player/video_top_bar_style.dart';
import 'package:gz_video_player_example/other_test_page.dart';
void main() {
runApp(const MyApp());
......@@ -87,6 +89,7 @@ class _VideoPlayerPageState extends State<VideoPlayerPage> {
}
GZVideoPlayerState? state;
VideoPlayerController? videoPlayerController;
@override
void initState() {
......@@ -396,6 +399,11 @@ class _VideoPlayerPageState extends State<VideoPlayerPage> {
})
],
/// 初始化完成
onInit: (VideoPlayerController controller) {
videoPlayerController = controller;
},
/// 视频暂停回调
onPause: (value) {
debugPrint("video paused");
......@@ -497,6 +505,19 @@ class _VideoPlayerPageState extends State<VideoPlayerPage> {
),
),
),
SliverToBoxAdapter(
child: Center(
child: CustomBtn(
title: 'to second page',
onTap: () {
videoPlayerController?.pause();
Navigator.of(context).push(MaterialPageRoute(builder: (BuildContext context){
return const OtherTestPage();
}));
},
),
),
),
],
),
)
......
import 'package:flutter/material.dart';
import 'package:gz_video_player/video.dart';
class OtherTestPage extends StatefulWidget {
const OtherTestPage({super.key});
@override
State<StatefulWidget> createState() => _OtherTestPageState();
}
class _OtherTestPageState extends State<OtherTestPage> {
String url =
'https://mpv.videocc.net/8f38fa3352/c/8f38fa3352a8cc8f70dd384edb9b21dc_1.mp4';
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('other test page'),
),
body: Column(
children: [
GZVideoPlayer(
dataSource: url,
sourceType: DataSourceType.network,
restoreVertical: false,
),
],
),
);
}
}
......@@ -357,6 +357,14 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.0.17"
visibility_detector:
dependency: transitive
description:
name: visibility_detector
sha256: dd5cc11e13494f432d15939c3aa8ae76844c42b723398643ce9addb88a5ed420
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.4.0+2"
wakelock:
dependency: transitive
description:
......
......@@ -18,6 +18,7 @@ import 'package:gz_video_player/widget/video_top_bar.dart';
import 'package:gz_video_player/widget/volume.dart';
import 'package:screen_brightness/screen_brightness.dart';
import 'package:video_player/video_player.dart';
import 'package:visibility_detector/visibility_detector.dart';
import 'package:wakelock/wakelock.dart';
export 'package:video_player/video_player.dart';
......@@ -32,6 +33,7 @@ class GZVideoPlayer extends StatefulWidget {
this.brightnessWidget,
this.volumeWidget,
this.children,
this.restoreVertical = true,
this.onInit,
this.onPlay,
this.onTimeUpdate,
......@@ -51,13 +53,16 @@ class GZVideoPlayer extends StatefulWidget {
final dynamic dataSource;
final DataSourceType sourceType;
/// 播放自定义属性
/// 播放自定义属性
final VideoPlayOptions playOptions;
final VideoStyle videoStyle;
final List<Widget>? children;
final Widget? brightnessWidget;
final Widget? volumeWidget;
/// 播放器释放时是否恢复竖屏,默认恢复竖屏
final bool restoreVertical;
/// 初始化完成回调事件
final ValueChanged<VideoPlayerController>? onInit;
......@@ -108,7 +113,7 @@ class GZVideoPlayer extends StatefulWidget {
}
class GZVideoPlayerState extends State<GZVideoPlayer>
with SingleTickerProviderStateMixin {
with SingleTickerProviderStateMixin, WidgetsBindingObserver {
/// 控制器 - 快进 seekTo 暂停 pause 播放 play 摧毁 dispose
late VideoPlayerController _controller;
......@@ -125,7 +130,7 @@ class GZVideoPlayerState extends State<GZVideoPlayer>
double? _originBrightness;
/// 视频音量
final ValueNotifier<double> _volume = ValueNotifier(0.5);
final ValueNotifier<double> _volume = ValueNotifier(1.0);
/// 是否显示控制拦
bool _showMenu = false;
......@@ -152,6 +157,12 @@ class GZVideoPlayerState extends State<GZVideoPlayer>
/// 获取屏幕大小
Size get screenSize => MediaQuery.of(context).size;
/// 是否显示
bool _hasShow = false;
/// 多播放器实例设置唯一key
Key key = Key(DateTime.now().toString());
late StreamSubscription<ConnectivityResult> _subscription;
@override
......@@ -173,38 +184,7 @@ class GZVideoPlayerState extends State<GZVideoPlayer>
.animate(_controlBarAnimationController);
var widgetsBinding = WidgetsBinding.instance;
//监听系统的每一帧
widgetsBinding.addPostFrameCallback((callback) {
widgetsBinding.addPersistentFrameCallback((callback) {
if (!mounted) return;
var orientation = MediaQuery.of(context).orientation;
bool fullscreen = false;
if (orientation == Orientation.landscape) {
//横屏
fullscreen = true;
SystemChrome.setEnabledSystemUIMode(
SystemUiMode.manual,
overlays: [],
);
} else if (orientation == Orientation.portrait) {
fullscreen = false;
SystemChrome.setEnabledSystemUIMode(
SystemUiMode.manual,
overlays: SystemUiOverlay.values,
);
}
if (fullscreen != _fullScreened) {
setState(() {
_fullScreened = !_fullScreened;
_navigateLocally(context);
//触发全屏事件
widget.onFullscreen?.call(_fullScreened);
});
}
//触发一帧的绘制
widgetsBinding.scheduleFrame();
});
});
widgetsBinding.addObserver(this);
/// 网络监听
_subscription = Connectivity()
......@@ -250,8 +230,10 @@ class GZVideoPlayerState extends State<GZVideoPlayer>
_controlBarAnimationController.dispose();
///恢复设备竖屏
// SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
GzOrientation.setPreferredOrientations([DeviceOrientation.portraitUp]);
if (widget.restoreVertical) {
GzOrientation.setPreferredOrientations([DeviceOrientation.portraitUp]);
}
Wakelock.toggle(enable: false);
_subscription.cancel();
_brightness.dispose();
......@@ -259,9 +241,41 @@ class GZVideoPlayerState extends State<GZVideoPlayer>
if (_originBrightness != null) {
ScreenBrightness().setScreenBrightness(_originBrightness!);
}
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
@override
void didChangeMetrics() {
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
if (!_hasShow) return;
var orientation = MediaQuery.of(context).orientation;
bool fullscreen = false;
if (orientation == Orientation.landscape) {
//横屏
fullscreen = true;
SystemChrome.setEnabledSystemUIMode(
SystemUiMode.manual,
overlays: [],
);
} else if (orientation == Orientation.portrait) {
fullscreen = false;
SystemChrome.setEnabledSystemUIMode(
SystemUiMode.manual,
overlays: SystemUiOverlay.values,
);
}
if (fullscreen != _fullScreened) {
setState(() {
_fullScreened = !_fullScreened;
_navigateLocally(context);
//触发全屏事件
widget.onFullscreen?.call(_fullScreened);
});
}
});
}
void _updateDataSource() async {
VideoPlayerController tempController = _createVideoPlayerController();
......@@ -313,6 +327,7 @@ class GZVideoPlayerState extends State<GZVideoPlayer>
// debugPrint("error: " + controller.value.errorDescription);
if (_controller.value.isPlaying) {
_controller.setPlaybackSpeed(_speedItem.speed);
setState(() {
if (oDuration.inHours == 0) {
var strPosition = oPosition.toString().split('.')[0];
......@@ -334,7 +349,6 @@ class GZVideoPlayerState extends State<GZVideoPlayer>
}
}
}
_controller.setPlaybackSpeed(_speedItem.speed);
}
}
......@@ -399,10 +413,8 @@ class GZVideoPlayerState extends State<GZVideoPlayer>
/// 点击全屏或取消
void toggleFullScreen() {
if (_fullScreened) {
// SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
GzOrientation.forceOrientation(DeviceOrientation.portraitUp);
} else {
// SystemChrome.setPreferredOrientations([DeviceOrientation.landscapeRight]);
GzOrientation.forceOrientation(DeviceOrientation.landscapeRight);
}
}
......@@ -872,13 +884,19 @@ class GZVideoPlayerState extends State<GZVideoPlayer>
videoChildrens.addAll(widget.children ?? []);
/// 构建video
return AspectRatio(
aspectRatio: _fullScreened
? _calculateAspectRatio(context)
: widget.playOptions.aspectRatio,
/// build 所有video组件
child: Stack(children: videoChildrens),
return VisibilityDetector(
key: key,
onVisibilityChanged: (VisibilityInfo info) {
_hasShow = info.visibleFraction >= 0.9;
},
child: AspectRatio(
aspectRatio: _fullScreened
? _calculateAspectRatio(context)
: widget.playOptions.aspectRatio,
/// build 所有video组件
child: Stack(children: videoChildrens),
),
);
}
......
......@@ -15,6 +15,8 @@ dependencies:
connectivity: ^3.0.6
screen_brightness: ^0.2.2+1
wakelock: ^0.6.2
# 检测组件是否在可视范围内
visibility_detector: ^0.4.0+2
gz_orientation:
git:
url: http://code.seevin.com/18223204110/gz_orientation.git
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论