111 lines
3.5 KiB
Dart
111 lines
3.5 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:get/get.dart';
|
|
import 'package:hgdj/hj_page/video/video_full_logic.dart';
|
|
import 'package:hgdj/hj_page/video/view/video_menu_view.dart';
|
|
import 'package:video_player/video_player.dart';
|
|
|
|
import '../../hj_model/video_model.dart';
|
|
import '../../hj_utils/screen.dart';
|
|
import '../../tools_base/unique_tag_mixin.dart';
|
|
|
|
/// 全屏播放页(复用外部传入的播放器控制器,不新建也不释放)
|
|
class VideoFullPage extends StatefulWidget {
|
|
final VideoPlayerController playCtr;
|
|
final VideoModel? videoModel;
|
|
final bool isAutoV; // 判断size,自动转竖屏
|
|
final bool showMenu; //是否需要显示菜单栏,直播不需要展示菜单栏
|
|
|
|
const VideoFullPage({
|
|
super.key,
|
|
required this.playCtr,
|
|
this.videoModel,
|
|
this.isAutoV = true,
|
|
this.showMenu = true,
|
|
});
|
|
|
|
@override
|
|
State<VideoFullPage> createState() => _VideoFullPageState();
|
|
}
|
|
|
|
// tag 隔离:logic 持有外部传入的 playCtr。不加 tag 时上一个全屏页的 Get.delete 若没跑完,
|
|
// GetBuilder 的 init 会被跳过 → 复用旧 logic、播到上一个视频
|
|
class _VideoFullPageState extends State<VideoFullPage> with UniqueTagMixin {
|
|
VideoPlayerController get playCtr => widget.playCtr;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return GetBuilder<VideoFullLogic>(
|
|
tag: uniqueTag,
|
|
init: VideoFullLogic(playCtr: playCtr, isAutoV: widget.isAutoV),
|
|
builder: (logic) => PopScope(
|
|
// 系统返回键/侧滑不直接退页,先恢复竖屏再由 exitFullScreen 退
|
|
canPop: false,
|
|
onPopInvokedWithResult: (didPop, _) {
|
|
if (didPop) return;
|
|
logic.exitFullScreen();
|
|
},
|
|
child: Scaffold(
|
|
backgroundColor: Colors.black,
|
|
body: Stack(
|
|
alignment: Alignment.center,
|
|
children: [
|
|
// 撑满 Stack 用(Stack 尺寸取最大的非 Positioned 子节点)。
|
|
// 不能改成 StackFit.expand:那会给 AspectRatio 传 tight 约束,视频比例失效
|
|
SizedBox(width: screen.screenWidth, height: screen.screenHeight),
|
|
Hero(
|
|
tag: "player",
|
|
child: AspectRatio(
|
|
aspectRatio: logic.aspectRatio,
|
|
child: VideoPlayer(playCtr),
|
|
),
|
|
),
|
|
if (widget.showMenu) _menuLayer(logic),
|
|
_backBtn(logic),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
/// 播放器控制层(进度条/倍速/快进快退)
|
|
Widget _menuLayer(VideoFullLogic logic) {
|
|
return Positioned(
|
|
bottom: 5,
|
|
left: 0,
|
|
right: 0,
|
|
child: SizedBox(
|
|
width: screen.screenWidth,
|
|
height: screen.screenHeight,
|
|
child: VideoMenuView(
|
|
playCtr: playCtr,
|
|
isFull: true,
|
|
onFullScreen: logic.exitFullScreen,
|
|
videoModel: widget.videoModel,
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
/// 全屏(横屏)下返回按钮避开刘海/状态栏安全区(原来用竖屏的 paddingTop 不准)
|
|
Widget _backBtn(VideoFullLogic logic) {
|
|
return SafeArea(
|
|
child: Align(
|
|
alignment: Alignment.topLeft,
|
|
child: InkWell(
|
|
enableFeedback: false,
|
|
onTap: logic.exitFullScreen,
|
|
child: const Padding(
|
|
padding: EdgeInsets.fromLTRB(5, 5, 15, 15),
|
|
child: SizedBox(
|
|
width: 30,
|
|
height: 30,
|
|
child: Icon(Icons.arrow_back_ios_sharp, color: Colors.white),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|