127 lines
3.6 KiB
Dart
127 lines
3.6 KiB
Dart
import 'dart:async';
|
|
|
|
import 'package:flutter/material.dart';
|
|
import 'package:get/get.dart';
|
|
import 'package:hgdj/assets_tool/images.dart';
|
|
import 'package:hgdj/hj_page/video/video_full_page.dart';
|
|
import 'package:hgdj/hj_page/video/view/video_menu_view.dart';
|
|
import 'package:hgdj/hj_utils/screen.dart';
|
|
import 'package:hgdj/hj_utils/video_view_type.dart';
|
|
import 'package:hgdj/tools_base/event_bus/event_bus_util.dart';
|
|
import 'package:hgdj/tools_base/event_bus/events.dart';
|
|
import 'package:hgdj/tools_base/loading/loading_center_widget.dart';
|
|
import 'package:video_player/video_player.dart';
|
|
|
|
import '../../tools_base/widget/net_image_widget.dart';
|
|
|
|
class VideoPlayerAlert extends StatefulWidget {
|
|
final String? movieUrl;
|
|
final String? imgCover;
|
|
|
|
const VideoPlayerAlert(this.movieUrl, {this.imgCover, super.key});
|
|
|
|
@override
|
|
State<VideoPlayerAlert> createState() => _VideoPlayerAlertState();
|
|
}
|
|
|
|
class _VideoPlayerAlertState extends State<VideoPlayerAlert> {
|
|
VideoPlayerController? videoCtr;
|
|
StreamSubscription? pauseSub;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
// 耳机/蓝牙断开、来电中断时暂停,防止外放泄露
|
|
pauseSub = eventBus.on<PauseVideoEvent>((_) => videoCtr?.pause());
|
|
WidgetsBinding.instance.addPostFrameCallback((_) => _initStatus());
|
|
}
|
|
|
|
void _initStatus({bool isRetry = false}) async {
|
|
videoCtr = PlayerFactory.network(widget.movieUrl);
|
|
try {
|
|
await videoCtr?.initialize();
|
|
if (isRetry)
|
|
confirmPlatformView(); // 仅重试成功(同视频 textureView 挂、platformView 放出)才落本地
|
|
if (mounted) {
|
|
videoCtr?.play();
|
|
setState(() {});
|
|
}
|
|
} catch (e) {
|
|
videoCtr?.dispose();
|
|
// 首次芯片解码/渲染报错:仅内存切 platformView 重试,成功后才落本地
|
|
if (isDecoderError(e) && switchToPlatformView()) {
|
|
_initStatus(isRetry: true);
|
|
}
|
|
}
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
pauseSub?.cancel();
|
|
videoCtr?.dispose();
|
|
super.dispose();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Dialog(
|
|
insetPadding: EdgeInsets.zero,
|
|
backgroundColor: Colors.transparent,
|
|
child: SafeArea(
|
|
child: Stack(
|
|
fit: StackFit.expand,
|
|
children: [
|
|
_buildContent(),
|
|
Positioned(
|
|
left: 0,
|
|
top: 0,
|
|
child: InkWell(
|
|
enableFeedback: false,
|
|
onTap: Get.back,
|
|
child: Container(
|
|
padding: EdgeInsets.only(left: 16, top: 6),
|
|
child: Image.asset('back_circle.png'.commonImgPath,
|
|
width: 24, height: 24),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildContent() {
|
|
// 未初始化完成:展示封面 + loading
|
|
if (videoCtr?.value.isInitialized != true) {
|
|
return Stack(
|
|
alignment: Alignment.center,
|
|
children: [
|
|
if (widget.imgCover?.isNotEmpty == true)
|
|
NetworkImageLoader(imageUrl: widget.imgCover ?? ""),
|
|
LoadingCenterWidget(),
|
|
],
|
|
);
|
|
}
|
|
return Stack(
|
|
fit: StackFit.expand,
|
|
children: [
|
|
Container(
|
|
alignment: Alignment.center,
|
|
width: screen.screenWidth,
|
|
child: AspectRatio(
|
|
aspectRatio: videoCtr!.value.aspectRatio,
|
|
child: VideoPlayer(videoCtr!),
|
|
),
|
|
),
|
|
VideoMenuView(
|
|
playCtr: videoCtr!,
|
|
isFull: true,
|
|
onFullScreen: () =>
|
|
Get.to(() => VideoFullPage(playCtr: videoCtr!, isAutoV: false)),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
}
|