diff --git a/lib/pages/danmaku/view.dart b/lib/pages/danmaku/view.dart index 81a70a9b..77fa8e8e 100644 --- a/lib/pages/danmaku/view.dart +++ b/lib/pages/danmaku/view.dart @@ -1,4 +1,3 @@ -import 'dart:async'; import 'dart:convert'; import 'package:PiliPlus/grpc/bilibili/community/service/dm/v1.pb.dart'; @@ -14,13 +13,15 @@ import 'package:get/get.dart'; class PlDanmaku extends StatefulWidget { final int cid; final PlPlayerController playerController; - final bool? isPipMode; + final bool isPipMode; + final bool isFullScreen; const PlDanmaku({ super.key, required this.cid, required this.playerController, - this.isPipMode, + this.isPipMode = false, + required this.isFullScreen, }); @override @@ -33,8 +34,6 @@ class _PlDanmakuState extends State { late PlDanmakuController _plDanmakuController; DanmakuController? _controller; int latestAddedPosition = -1; - bool? _isFullScreen; - StreamSubscription? _listenerFS; @override void initState() { @@ -53,20 +52,27 @@ class _PlDanmakuState extends State { playerController ..addStatusLister(playerListener) ..addPositionListener(videoPositionListen); - _listenerFS = playerController.isFullScreen.listen((isFullScreen) { - if (isFullScreen != _isFullScreen) { - _isFullScreen = isFullScreen; - if (_controller != null) { - _controller!.updateOption( - _controller!.option.copyWith( - fontSize: _getFontSize(isFullScreen), - ), - ); - } - } - }); } + @override + void didUpdateWidget(PlDanmaku oldWidget) { + super.didUpdateWidget(oldWidget); + if (oldWidget.isPipMode != widget.isPipMode || + oldWidget.isFullScreen != widget.isFullScreen) { + _updateFontSize(); + } + } + + void _updateFontSize() { + _controller?.updateOption( + _controller!.option.copyWith(fontSize: _fontSize), + ); + } + + double get _fontSize => !widget.isFullScreen || widget.isPipMode + ? 15 * playerController.danmakuFontScale + : 15 * playerController.danmakuFontScaleFS; + // 播放器状态监听 void playerListener(PlayerStatus? status) { if (status == PlayerStatus.playing) { @@ -77,15 +83,11 @@ class _PlDanmakuState extends State { } void videoPositionListen(Duration position) { - if (!playerController.enableShowDanmaku.value) { + if (_controller == null || !playerController.enableShowDanmaku.value) { return; } - if (_controller == null) { - return; - } - - if (!playerController.showDanmaku && widget.isPipMode != true) { + if (!playerController.showDanmaku && !widget.isPipMode) { return; } @@ -138,7 +140,6 @@ class _PlDanmakuState extends State { @override void dispose() { - _listenerFS?.cancel(); playerController ..removePositionListener(videoPositionListen) ..removeStatusLister(playerListener); @@ -146,45 +147,35 @@ class _PlDanmakuState extends State { super.dispose(); } - double _getFontSize(bool isFullScreen) => - !isFullScreen || widget.isPipMode == true - ? 15 * playerController.danmakuFontScale - : 15 * playerController.danmakuFontScaleFS; - @override Widget build(BuildContext context) { - return LayoutBuilder( - builder: (context, box) { - // double initDuration = box.maxWidth / 12; - return Obx( - () => AnimatedOpacity( - opacity: playerController.enableShowDanmaku.value ? 1 : 0, - duration: const Duration(milliseconds: 100), - child: DanmakuScreen( - createdController: (DanmakuController e) { - playerController.danmakuController = _controller = e; - }, - option: DanmakuOption( - fontSize: _getFontSize(playerController.isFullScreen.value), - fontWeight: playerController.fontWeight, - area: playerController.showArea, - opacity: playerController.danmakuOpacity, - hideTop: playerController.blockTypes.contains(5), - hideScroll: playerController.blockTypes.contains(2), - hideBottom: playerController.blockTypes.contains(4), - duration: - playerController.danmakuDuration / - playerController.playbackSpeed, - staticDuration: - playerController.danmakuStaticDuration / - playerController.playbackSpeed, - strokeWidth: playerController.strokeWidth, - lineHeight: playerController.danmakuLineHeight, - ), - ), + return Obx( + () => AnimatedOpacity( + opacity: playerController.enableShowDanmaku.value ? 1 : 0, + duration: const Duration(milliseconds: 100), + child: DanmakuScreen( + createdController: (DanmakuController e) { + playerController.danmakuController = _controller = e; + }, + option: DanmakuOption( + fontSize: _fontSize, + fontWeight: playerController.fontWeight, + area: playerController.showArea, + opacity: playerController.danmakuOpacity, + hideTop: playerController.blockTypes.contains(5), + hideScroll: playerController.blockTypes.contains(2), + hideBottom: playerController.blockTypes.contains(4), + duration: + playerController.danmakuDuration / + playerController.playbackSpeed, + staticDuration: + playerController.danmakuStaticDuration / + playerController.playbackSpeed, + strokeWidth: playerController.strokeWidth, + lineHeight: playerController.danmakuLineHeight, ), - ); - }, + ), + ), ); } } diff --git a/lib/pages/history/widgets/item.dart b/lib/pages/history/widgets/item.dart index 4a90c00e..f6f8f237 100644 --- a/lib/pages/history/widgets/item.dart +++ b/lib/pages/history/widgets/item.dart @@ -36,6 +36,7 @@ class HistoryItem extends StatelessWidget { final hasDuration = item.duration != null && item.duration != 0; int aid = item.history.oid!; String bvid = item.history.bvid ?? IdUtils.av2bv(aid); + final business = item.history.business; return Material( type: MaterialType.transparency, child: InkWell( @@ -44,25 +45,25 @@ class HistoryItem extends StatelessWidget { ctr.onSelect(item); return; } - if (item.history.business?.contains('article') == true) { + if (business?.contains('article') == true) { PageUtils.toDupNamed( '/articlePage', parameters: { - 'id': item.history.business == 'article-list' + 'id': business == 'article-list' ? '${item.history.cid}' : '${item.history.oid}', 'type': 'read', }, ); - } else if (item.history.business == 'live') { + } else if (business == 'live') { if (item.liveStatus == 1) { PageUtils.toLiveRoom(item.history.oid); } else { SmartDialog.showToast('直播未开播'); } - } else if (item.history.business == 'pgc') { + } else if (business == 'pgc') { PageUtils.viewPgc(epId: item.history.epid); - } else if (item.history.business == 'cheese') { + } else if (business == 'cheese') { if (item.uri?.isNotEmpty == true) { PageUtils.viewPgcFromUri( item.uri!, @@ -144,8 +145,7 @@ class HistoryItem extends StatelessWidget { top: 6.0, right: 6.0, type: - item.history.business == - HistoryBusinessType.live.type && + business == HistoryBusinessType.live.type && item.liveStatus != 1 ? PBadgeType.gray : PBadgeType.primary, @@ -255,11 +255,11 @@ class HistoryItem extends StatelessWidget { ], ), ), - if (item.history.business != 'pgc' && + if (business != 'pgc' && item.badge != '番剧' && item.tagName?.contains('动画') != true && - item.history.business != 'live' && - item.history.business?.contains('article') != true) + business != 'live' && + business?.contains('article') != true) PopupMenuItem( onTap: () async { var res = await UserHttp.toViewLater( @@ -277,8 +277,7 @@ class HistoryItem extends StatelessWidget { ), ), PopupMenuItem( - onTap: () => - onDelete(item.kid!, item.history.business!), + onTap: () => onDelete(item.kid!, business!), height: 35, child: const Row( children: [ diff --git a/lib/pages/live_room/controller.dart b/lib/pages/live_room/controller.dart index e5febb69..50359907 100644 --- a/lib/pages/live_room/controller.dart +++ b/lib/pages/live_room/controller.dart @@ -40,8 +40,6 @@ class LiveRoomController extends GetxController { // dm LiveDmInfoData? dmInfo; - bool showDanmaku = true; - DanmakuController? controller; List? savedDanmaku; RxList messages = [].obs; RxBool disableAutoScroll = false.obs; @@ -289,8 +287,9 @@ class LiveRoomController extends GetxController { 'emots': extra['emots'], 'uemote': first[13], }); - if (showDanmaku) { - controller?.addDanmaku( + + if (plPlayerController.showDanmaku) { + plPlayerController.danmakuController?.addDanmaku( DanmakuContentItem( extra['content'], color: DmUtils.decimalToColor(extra['color']), diff --git a/lib/pages/live_room/view.dart b/lib/pages/live_room/view.dart index ffd40ed7..5c0814c4 100644 --- a/lib/pages/live_room/view.dart +++ b/lib/pages/live_room/view.dart @@ -1,4 +1,3 @@ -import 'dart:async'; import 'dart:io'; import 'dart:ui'; @@ -12,6 +11,7 @@ import 'package:PiliPlus/pages/live_room/widgets/chat.dart'; import 'package:PiliPlus/pages/live_room/widgets/header_control.dart'; import 'package:PiliPlus/plugin/pl_player/controller.dart'; import 'package:PiliPlus/plugin/pl_player/models/play_status.dart'; +import 'package:PiliPlus/plugin/pl_player/utils/fullscreen.dart'; import 'package:PiliPlus/plugin/pl_player/view.dart'; import 'package:PiliPlus/services/service_locator.dart'; import 'package:PiliPlus/utils/extension.dart'; @@ -23,7 +23,7 @@ import 'package:cached_network_image/cached_network_image.dart'; import 'package:canvas_danmaku/canvas_danmaku.dart'; import 'package:floating/floating.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/services.dart' show MethodChannel, SystemUiOverlayStyle; +import 'package:flutter/services.dart' show SystemUiOverlayStyle; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; import 'package:screen_brightness/screen_brightness.dart'; @@ -42,14 +42,8 @@ class _LiveRoomPageState extends State late final PlPlayerController plPlayerController; bool get isFullScreen => plPlayerController.isFullScreen.value; - StreamSubscription? _listener; - - bool? _isFullScreen; - bool? _isPipMode; - final GlobalKey chatKey = GlobalKey(); final GlobalKey playerKey = GlobalKey(); - final GlobalKey videoPlayerKey = GlobalKey(); final Color _color = const Color(0xFFEEEEEE); @@ -66,12 +60,6 @@ class _LiveRoomPageState extends State plPlayerController ..autoEnterFullscreen() ..addStatusLister(playerListener); - _listener = plPlayerController.isFullScreen.listen((isFullScreen) { - if (isFullScreen != _isFullScreen) { - _isFullScreen = isFullScreen; - _updateFontSize(); - } - }); } void playerListener(PlayerStatus? status) { @@ -86,31 +74,9 @@ class _LiveRoomPageState extends State } } - Future _updateFontSize() async { - if (Platform.isAndroid) { - _isPipMode = await const MethodChannel( - "floating", - ).invokeMethod('inPipAlready'); - } - if (_liveRoomController.controller != null) { - _liveRoomController.controller!.updateOption( - _liveRoomController.controller!.option.copyWith( - fontSize: _getFontSize(isFullScreen), - ), - ); - } - } - - double _getFontSize(bool isFullScreen) { - return isFullScreen == false || _isPipMode == true - ? 15 * plPlayerController.danmakuFontScale - : 15 * plPlayerController.danmakuFontScaleFS; - } - @override void dispose() { videoPlayerServiceHandler.onVideoDetailDispose(heroTag); - _listener?.cancel(); WidgetsBinding.instance.removeObserver(this); ScreenBrightness.instance.resetApplicationScreenBrightness(); PlPlayerController.setPlayCallBack(null); @@ -126,30 +92,38 @@ class _LiveRoomPageState extends State @override void didChangeAppLifecycleState(AppLifecycleState state) { if (state == AppLifecycleState.resumed) { - _liveRoomController.showDanmaku = true; + if (!plPlayerController.showDanmaku) { + plPlayerController.showDanmaku = true; + if (isFullScreen && Platform.isIOS) { + WidgetsBinding.instance.addPostFrameCallback((_) { + if (!_liveRoomController.isPortrait.value) { + landScape(); + } + }); + } + } } else if (state == AppLifecycleState.paused) { - _liveRoomController.showDanmaku = false; - plPlayerController.danmakuController?.clear(); + plPlayerController + ..showDanmaku = false + ..danmakuController?.clear(); } } @override Widget build(BuildContext context) { - WidgetsBinding.instance.addPostFrameCallback((_) { - _updateFontSize(); - }); - final isPortrait = context.isPortrait; if (Platform.isAndroid) { return Floating().isPipMode - ? videoPlayerPanel() + ? videoPlayerPanel(isFullScreen, isPipMode: true) : childWhenDisabled(isPortrait); } else { return childWhenDisabled(isPortrait); } } - Widget videoPlayerPanel({ + Widget videoPlayerPanel( + bool isFullScreen, { + bool isPipMode = false, Color? fill, Alignment? alignment, bool needDm = true, @@ -183,36 +157,10 @@ class _LiveRoomPageState extends State ), danmuWidget: !needDm ? null - : Obx( - () => AnimatedOpacity( - opacity: plPlayerController.enableShowDanmaku.value - ? 1 - : 0, - duration: const Duration(milliseconds: 100), - child: DanmakuScreen( - createdController: (DanmakuController e) { - plPlayerController.danmakuController = - _liveRoomController.controller = e; - }, - option: DanmakuOption( - fontSize: _getFontSize(isFullScreen), - fontWeight: plPlayerController.fontWeight, - area: plPlayerController.showArea, - opacity: plPlayerController.danmakuOpacity, - hideTop: plPlayerController.blockTypes.contains(5), - hideScroll: plPlayerController.blockTypes.contains(2), - hideBottom: plPlayerController.blockTypes.contains(4), - duration: - plPlayerController.danmakuDuration / - plPlayerController.playbackSpeed, - staticDuration: - plPlayerController.danmakuStaticDuration / - plPlayerController.playbackSpeed, - strokeWidth: plPlayerController.strokeWidth, - lineHeight: plPlayerController.danmakuLineHeight, - ), - ), - ), + : LiveDanmaku( + plPlayerController: plPlayerController, + isFullScreen: isFullScreen, + isPipMode: isPipMode, ), ); } @@ -303,18 +251,14 @@ class _LiveRoomPageState extends State Widget get _buildPH { final isFullScreen = this.isFullScreen; final size = Get.size; - Widget child = SizedBox( - width: size.width, - height: isFullScreen ? size.height : size.width * 9 / 16, - child: videoPlayerPanel(), - ); - if (isFullScreen) { - return child; - } return Column( children: [ - _buildAppBar, - child, + if (!isFullScreen) _buildAppBar, + SizedBox( + width: size.width, + height: isFullScreen ? size.height : size.width * 9 / 16, + child: videoPlayerPanel(isFullScreen), + ), ..._buildBottomWidget, ], ); @@ -322,36 +266,38 @@ class _LiveRoomPageState extends State Widget get _buildPP { final isFullScreen = this.isFullScreen; - - final child = videoPlayerPanel( - alignment: isFullScreen ? null : Alignment.topCenter, - needDm: isFullScreen, + Widget child = Stack( + clipBehavior: Clip.none, + children: [ + Positioned.fill( + child: videoPlayerPanel( + isFullScreen, + alignment: isFullScreen ? null : Alignment.topCenter, + needDm: isFullScreen, + ), + ), + Positioned( + left: 0, + right: 0, + bottom: 55, + child: Visibility( + maintainState: true, + visible: !isFullScreen, + child: SizedBox( + height: Get.height * 0.32, + child: _buildChatWidget(true), + ), + ), + ), + ], ); - if (isFullScreen) { return child; } - return Column( children: [ _buildAppBar, - Expanded( - child: Stack( - clipBehavior: Clip.none, - children: [ - Positioned.fill(child: child), - Positioned( - left: 0, - right: 0, - bottom: 55, - child: SizedBox( - height: Get.height * 0.32, - child: _buildChatWidget(true), - ), - ), - ], - ), - ), + Expanded(child: child), _buildInputWidget, ], ); @@ -362,7 +308,6 @@ class _LiveRoomPageState extends State return AppBar( backgroundColor: Colors.transparent, foregroundColor: Colors.white, - toolbarHeight: isFullScreen ? 0 : null, titleTextStyle: const TextStyle(color: Colors.white), title: Obx( () { @@ -482,13 +427,26 @@ class _LiveRoomPageState extends State () { final isFullScreen = this.isFullScreen; final size = Get.size; - Widget child = Container( - margin: EdgeInsets.only( - bottom: MediaQuery.paddingOf(context).bottom, - ), - width: isFullScreen ? size.width : videoWidth, - height: isFullScreen ? size.height : size.width * 9 / 16, - child: videoPlayerPanel(fill: Colors.transparent), + Widget child = Row( + children: [ + Container( + margin: EdgeInsets.only( + bottom: MediaQuery.paddingOf(context).bottom, + ), + width: isFullScreen ? size.width : videoWidth, + height: isFullScreen ? size.height : size.width * 9 / 16, + child: videoPlayerPanel( + isFullScreen, + fill: Colors.transparent, + ), + ), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: _buildBottomWidget, + ), + ), + ], ); if (isFullScreen) { return child; @@ -496,19 +454,7 @@ class _LiveRoomPageState extends State return Column( children: [ _buildAppBar, - Expanded( - child: Row( - children: [ - child, - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: _buildBottomWidget, - ), - ), - ], - ), - ), + Expanded(child: child), ], ); }, @@ -630,3 +576,82 @@ class _LiveRoomPageState extends State ); } } + +class LiveDanmaku extends StatefulWidget { + final PlPlayerController plPlayerController; + final bool isPipMode; + final bool isFullScreen; + + const LiveDanmaku({ + super.key, + required this.plPlayerController, + this.isPipMode = false, + required this.isFullScreen, + }); + + @override + State createState() => _LiveDanmakuState(); +} + +class _LiveDanmakuState extends State { + PlPlayerController get plPlayerController => widget.plPlayerController; + + @override + void didUpdateWidget(LiveDanmaku oldWidget) { + super.didUpdateWidget(oldWidget); + if (oldWidget.isPipMode != widget.isPipMode || + oldWidget.isFullScreen != widget.isFullScreen) { + _updateFontSize(); + } + } + + void _updateFontSize() { + plPlayerController.danmakuController?.updateOption( + plPlayerController.danmakuController!.option.copyWith( + fontSize: _fontSize, + ), + ); + } + + double get _fontSize => !widget.isFullScreen || widget.isPipMode + ? 15 * plPlayerController.danmakuFontScale + : 15 * plPlayerController.danmakuFontScaleFS; + + @override + Widget build(BuildContext context) { + return Obx( + () { + return AnimatedOpacity( + opacity: plPlayerController.enableShowDanmaku.value ? 1 : 0, + duration: const Duration(milliseconds: 100), + child: DanmakuScreen( + createdController: (DanmakuController e) { + plPlayerController.danmakuController = e; + }, + option: DanmakuOption( + fontSize: _fontSize, + fontWeight: plPlayerController.fontWeight, + area: plPlayerController.showArea, + opacity: plPlayerController.danmakuOpacity, + hideTop: plPlayerController.blockTypes.contains(5), + hideScroll: plPlayerController.blockTypes.contains( + 2, + ), + hideBottom: plPlayerController.blockTypes.contains( + 4, + ), + duration: + plPlayerController.danmakuDuration / + plPlayerController.playbackSpeed, + staticDuration: + plPlayerController.danmakuStaticDuration / + plPlayerController.playbackSpeed, + strokeWidth: plPlayerController.strokeWidth, + lineHeight: plPlayerController.danmakuLineHeight, + ), + ), + ); + }, + ); + } +} diff --git a/lib/pages/live_room/widgets/chat.dart b/lib/pages/live_room/widgets/chat.dart index 023f8ce7..cf8a1ea9 100644 --- a/lib/pages/live_room/widgets/chat.dart +++ b/lib/pages/live_room/widgets/chat.dart @@ -28,7 +28,6 @@ class LiveRoomChat extends StatelessWidget { ? Colors.white.withValues(alpha: 0.9) : Colors.white.withValues(alpha: 0.6); return Stack( - clipBehavior: Clip.none, children: [ Obx( () => ListView.separated( diff --git a/lib/pages/video/controller.dart b/lib/pages/video/controller.dart index 99fdc124..66ba2c18 100644 --- a/lib/pages/video/controller.dart +++ b/lib/pages/video/controller.dart @@ -102,8 +102,6 @@ class VideoDetailController extends GetxController late VideoDecodeFormatType currentDecodeFormats; // 是否开始自动播放 存在多p的情况下,第二p需要为true final RxBool autoPlay = true.obs; - // 封面图的展示 - final RxBool isShowCover = true.obs; final scaffoldKey = GlobalKey(); final childKey = GlobalKey(); @@ -285,7 +283,6 @@ class VideoDetailController extends GetxController ); autoPlay.value = Pref.autoPlayEnable; - if (autoPlay.value) isShowCover.value = false; // 预设的解码格式 cacheDecode = Pref.defaultDecode; @@ -732,7 +729,7 @@ class VideoDetailController extends GetxController ); if (positionSubscription == null && - !isShowCover.value && + autoPlay.value && plPlayerController.videoPlayerController != null) { final currPost = plPlayerController.position.value.inMilliseconds; @@ -781,7 +778,7 @@ class VideoDetailController extends GetxController ); if (positionSubscription == null && - (!isShowCover.value || plPlayerController.preInitPlayer)) { + (autoPlay.value || plPlayerController.preInitPlayer)) { initSkip(); plPlayerController.segmentList.value = segmentProgressList!; } @@ -799,7 +796,7 @@ class VideoDetailController extends GetxController ?.stream .position .listen((position) { - if (isShowCover.value) { + if (!autoPlay.value) { return; } int currentPos = position.inSeconds; @@ -1000,7 +997,7 @@ class VideoDetailController extends GetxController /// 更新画质、音质 void updatePlayer() { - isShowCover.value = false; + autoPlay.value = true; playedTime = plPlayerController.position.value; plPlayerController.removeListeners(); plPlayerController.isBuffering.value = false; @@ -1209,10 +1206,7 @@ class VideoDetailController extends GetxController setVideoHeight(); currentDecodeFormats = VideoDecodeFormatTypeExt.fromString('avc1')!; currentVideoQa = VideoQuality.fromCode(data.quality!); - if (autoPlay.value) { - isShowCover.value = false; - await playerInit(); - } else if (plPlayerController.preInitPlayer) { + if (autoPlay.value || plPlayerController.preInitPlayer) { await playerInit(); } isQuerying = false; @@ -1221,7 +1215,6 @@ class VideoDetailController extends GetxController if (data.dash == null) { SmartDialog.showToast('视频资源不存在'); autoPlay.value = false; - isShowCover.value = true; videoState.value = const Error('视频资源不存在'); if (plPlayerController.isFullScreen.value) { plPlayerController.toggleFullScreen(false); @@ -1340,15 +1333,11 @@ class VideoDetailController extends GetxController ? Duration.zero : Duration(milliseconds: data.lastPlayTime!)); } - if (autoPlay.value) { - isShowCover.value = false; - await playerInit(); - } else if (plPlayerController.preInitPlayer) { + if (autoPlay.value || plPlayerController.preInitPlayer) { await playerInit(); } } else { autoPlay.value = false; - isShowCover.value = true; videoState.value = Error(result['msg']); if (plPlayerController.isFullScreen.value) { plPlayerController.toggleFullScreen(false); diff --git a/lib/pages/video/view.dart b/lib/pages/video/view.dart index 5d0afbca..aed8a3c5 100644 --- a/lib/pages/video/view.dart +++ b/lib/pages/video/view.dart @@ -121,6 +121,7 @@ class _VideoDetailPageVState extends State final GlobalKey relatedVideoPanelKey = GlobalKey(); final GlobalKey videoPlayerKey = GlobalKey(); + final GlobalKey playerKey = GlobalKey(); final GlobalKey videoReplyPanelKey = GlobalKey(); late final GlobalKey ugcPanelKey = GlobalKey(); late final GlobalKey pgcPanelKey = GlobalKey(); @@ -188,24 +189,26 @@ class _VideoDetailPageVState extends State @override void didChangeAppLifecycleState(AppLifecycleState state) { if (state == AppLifecycleState.resumed) { - introController.startTimer(); - videoDetailController.plPlayerController.showDanmaku = true; + if (!videoDetailController.plPlayerController.showDanmaku) { + introController.startTimer(); + videoDetailController.plPlayerController.showDanmaku = true; - // 修复从后台恢复时全屏状态下屏幕方向错误的问题 - if (isFullScreen && Platform.isIOS) { - WidgetsBinding.instance.addPostFrameCallback((_) { - // 根据视频方向重新设置屏幕方向 - final isVertical = videoDetailController.isVertical.value; - final mode = plPlayerController?.mode; + // 修复从后台恢复时全屏状态下屏幕方向错误的问题 + if (isFullScreen && Platform.isIOS) { + WidgetsBinding.instance.addPostFrameCallback((_) { + // 根据视频方向重新设置屏幕方向 + final isVertical = videoDetailController.isVertical.value; + final mode = plPlayerController?.mode; - late final size = Get.size; - if (!(mode == FullScreenMode.vertical || - (mode == FullScreenMode.auto && isVertical) || - (mode == FullScreenMode.ratio && - (isVertical || size.height / size.width < 1.25)))) { - landScape(); - } - }); + late final size = Get.size; + if (!(mode == FullScreenMode.vertical || + (mode == FullScreenMode.auto && isVertical) || + (mode == FullScreenMode.ratio && + (isVertical || size.height / size.width < 1.25)))) { + landScape(); + } + }); + } } } else if (state == AppLifecycleState.paused) { introController.canelTimer(); @@ -317,9 +320,7 @@ class _VideoDetailPageVState extends State return; } plPlayerController = videoDetailController.plPlayerController; - videoDetailController - ..isShowCover.value = false - ..autoPlay.value = true; + videoDetailController.autoPlay.value = true; if (videoDetailController.plPlayerController.preInitPlayer) { await plPlayerController!.play(); } else { @@ -452,9 +453,7 @@ class _VideoDetailPageVState extends State } } super.didPopNext(); - final isShowCover = videoDetailController.isShowCover.value; - videoDetailController.autoPlay.value = !isShowCover; - if (!isShowCover) { + if (videoDetailController.autoPlay.value) { await videoDetailController.playerInit( autoplay: videoDetailController.playerStatus == PlayerStatus.playing, ); @@ -1212,41 +1211,8 @@ class _VideoDetailPageVState extends State ), ); - Widget get childWhenEnabled => Obx( - () => !videoDetailController.autoPlay.value - ? const SizedBox.shrink() - : PLVideoPlayer( - key: Key(heroTag), - plPlayerController: plPlayerController!, - videoDetailController: videoDetailController, - ugcIntroController: videoDetailController.isUgc - ? ugcIntroController - : null, - pgcIntroController: videoDetailController.isUgc - ? null - : pgcIntroController, - headerControl: HeaderControl( - controller: plPlayerController!, - videoDetailCtr: videoDetailController, - heroTag: heroTag, - ), - danmuWidget: pipNoDanmaku - ? null - : Obx( - () => PlDanmaku( - key: Key(videoDetailController.cid.value.toString()), - isPipMode: true, - cid: videoDetailController.cid.value, - playerController: plPlayerController!, - ), - ), - showEpisodes: showEpisodes, - showViewPoints: showViewPoints, - ), - ); - Widget get manualPlayerWidget => Obx(() { - if (videoDetailController.isShowCover.value) { + if (!videoDetailController.autoPlay.value) { return Stack( clipBehavior: Clip.none, children: [ @@ -1387,15 +1353,15 @@ class _VideoDetailPageVState extends State return const SizedBox.shrink(); }); - Widget get plPlayer => Obx( + Widget plPlayer([bool isPipMode = false]) => Obx( key: videoPlayerKey, - () => videoDetailController.videoState.value is! Success - ? const SizedBox.shrink() - : !videoDetailController.autoPlay.value || - plPlayerController?.videoController == null + () => + videoDetailController.videoState.value is! Success || + !videoDetailController.autoPlay.value || + plPlayerController?.videoController == null ? const SizedBox.shrink() : PLVideoPlayer( - key: Key(heroTag), + key: playerKey, plPlayerController: plPlayerController!, videoDetailController: videoDetailController, ugcIntroController: videoDetailController.isUgc @@ -1410,13 +1376,17 @@ class _VideoDetailPageVState extends State videoDetailCtr: videoDetailController, heroTag: heroTag, ), - danmuWidget: Obx( - () => PlDanmaku( - key: Key(videoDetailController.cid.value.toString()), - cid: videoDetailController.cid.value, - playerController: plPlayerController!, - ), - ), + danmuWidget: isPipMode && pipNoDanmaku + ? null + : Obx( + () => PlDanmaku( + key: ValueKey(videoDetailController.cid.value), + isPipMode: isPipMode, + cid: videoDetailController.cid.value, + playerController: plPlayerController!, + isFullScreen: plPlayerController!.isFullScreen.value, + ), + ), showEpisodes: showEpisodes, showViewPoints: showViewPoints, ), @@ -1424,7 +1394,7 @@ class _VideoDetailPageVState extends State Widget autoChoose(Widget childWhenDisabled) { if (Platform.isAndroid) { - return Floating().isPipMode ? childWhenEnabled : childWhenDisabled; + return Floating().isPipMode ? plPlayer(true) : childWhenDisabled; } return childWhenDisabled; } @@ -1624,10 +1594,10 @@ class _VideoDetailPageVState extends State children: [ const Positioned.fill(child: ColoredBox(color: Colors.black)), - if (isShowing) plPlayer, + if (isShowing) plPlayer(), Obx(() { - if (videoDetailController.isShowCover.value) { + if (!videoDetailController.autoPlay.value) { return Positioned.fill( child: GestureDetector( onTap: handlePlay,