Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion lib/pages/danmaku/view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import 'package:PiliPlus/pages/danmaku/danmaku_model.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/danmaku_options.dart';
import 'package:PiliPlus/plugin/pl_player/utils/fullscreen.dart';
import 'package:PiliPlus/utils/danmaku_utils.dart';
import 'package:canvas_danmaku/canvas_danmaku.dart';
import 'package:flutter/material.dart';
Expand All @@ -19,6 +20,7 @@ class PlDanmaku extends StatefulWidget {
final bool isFullScreen;
final bool isFileSource;
final Size size;
final double? topInset;

const PlDanmaku({
super.key,
Expand All @@ -28,6 +30,7 @@ class PlDanmaku extends StatefulWidget {
required this.isFullScreen,
required this.isFileSource,
required this.size,
this.topInset,
});

@override
Expand Down Expand Up @@ -173,6 +176,17 @@ class _PlDanmakuState extends State<PlDanmaku> {
notFullscreen: widget.notFullscreen,
speed: playerController.playbackSpeed,
);
// 竖屏全屏时与顶部控件共用同一套顶部避让,并把可视高度同步减去,
// 让弹幕轨道按缩小后的区域正确排布
final inset = portraitFullscreenTopInset(
isFullScreen: widget.isFullScreen,
isPortrait: widget.size.height >= widget.size.width,
removeSafeArea: playerController.removeSafeArea,
topInset: widget.topInset,
);
final danmakuSize = inset == null
? widget.size
: Size(widget.size.width, widget.size.height - inset);
return Obx(
() => AnimatedOpacity(
opacity: playerController.enableShowDanmaku.value
Expand All @@ -184,7 +198,7 @@ class _PlDanmakuState extends State<PlDanmaku> {
playerController.danmakuController = _controller = e;
},
option: option,
size: widget.size,
size: danmakuSize,
),
),
);
Expand Down
1 change: 1 addition & 0 deletions lib/pages/video/view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1418,6 +1418,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
isFullScreen: plPlayerController!.isFullScreen.value,
isFileSource: videoDetailController.isFileSource,
size: Size(width, height),
topInset: _fixedTopInset,
),
),
showEpisodes: showEpisodes,
Expand Down
14 changes: 14 additions & 0 deletions lib/plugin/pl_player/utils/fullscreen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,20 @@ import 'package:os_type/os_type.dart';
/// 才“长高”导致整体下移一跳。
const Duration kSystemBarSettleDelay = Duration(milliseconds: 120);

/// 竖屏全屏时的顶部避让高度:仅在全屏 + 竖屏 + 未移除安全边距时返回
/// [topInset](进全屏前捕获的状态栏/挖孔高度),否则返回 null(不避让)。
/// 播控顶部组件与弹幕共用这一套判断,保证两处行为一致。
double? portraitFullscreenTopInset({
required bool isFullScreen,
required bool isPortrait,
required bool removeSafeArea,
required double? topInset,
}) {
if (!isFullScreen || !isPortrait || removeSafeArea) return null;
final inset = topInset ?? 0;
return inset > 0 ? inset : null;
}

bool _isDesktopFullScreen = false;

@pragma('vm:notify-debugger-on-exception')
Expand Down
15 changes: 14 additions & 1 deletion lib/plugin/pl_player/view/view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ import 'package:PiliPlus/plugin/pl_player/models/fullscreen_mode.dart';
import 'package:PiliPlus/plugin/pl_player/models/gesture_type.dart';
import 'package:PiliPlus/plugin/pl_player/models/play_status.dart';
import 'package:PiliPlus/plugin/pl_player/models/video_fit_type.dart';
import 'package:PiliPlus/plugin/pl_player/utils/fullscreen.dart';
import 'package:PiliPlus/plugin/pl_player/widgets/top_inset_padding.dart';
import 'package:PiliPlus/plugin/pl_player/widgets/app_bar_ani.dart';
import 'package:PiliPlus/plugin/pl_player/widgets/backward_seek.dart';
import 'package:PiliPlus/plugin/pl_player/widgets/bottom_control.dart';
Expand Down Expand Up @@ -1411,7 +1413,18 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
_videoWidget,

if (widget.danmuWidget case final danmaku?)
Positioned.fill(top: 4, child: danmaku),
Positioned.fill(
top: 4,
child: TopInsetPadding(
inset: portraitFullscreenTopInset(
isFullScreen: isFullScreen,
isPortrait: maxHeight >= maxWidth,
removeSafeArea: plPlayerController.removeSafeArea,
topInset: widget.topInset,
),
child: danmaku,
),
),

if (!isLive)
// 鸿蒙 media_kit fork 的 SubtitleView 没有上游 fork 的
Expand Down
23 changes: 12 additions & 11 deletions lib/plugin/pl_player/widgets/app_bar_ani.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import 'package:PiliPlus/common/widgets/view_safe_area.dart';
import 'package:PiliPlus/plugin/pl_player/utils/fullscreen.dart';
import 'package:PiliPlus/plugin/pl_player/widgets/top_inset_padding.dart';
import 'package:flutter/material.dart';

class AppBarAni extends StatelessWidget {
Expand Down Expand Up @@ -53,24 +55,23 @@ class AppBarAni extends StatelessWidget {

@override
Widget build(BuildContext context) {
final top = portraitFullscreenTopInset(
isFullScreen: isFullScreen,
isPortrait:
MediaQuery.sizeOf(context).height >= MediaQuery.sizeOf(context).width,
removeSafeArea: removeSafeArea,
topInset: topInset,
);
Widget result = child;
if (!removeSafeArea) {
result = ViewSafeArea(
left: isFullScreen,
right: isFullScreen,
child: result,
);
// 竖屏全屏时用进全屏前捕获的固定高度避让挖孔/状态栏,
// 不依赖全屏下已归零的 MediaQuery padding
if (isTop &&
isFullScreen &&
MediaQuery.sizeOf(context).height >= MediaQuery.sizeOf(context).width &&
(topInset ?? 0) > 0) {
result = Padding(
padding: EdgeInsets.only(top: topInset!),
child: result,
);
}
// 与弹幕共用同一套顶部避让(TopInsetPadding),
// 仅顶部栏需要,底部栏不避让
result = TopInsetPadding(inset: isTop ? top : null, child: result);
}
return SlideTransition(
position: controller.drive(isTop ? _topPos : _bottomPos),
Expand Down
18 changes: 18 additions & 0 deletions lib/plugin/pl_player/widgets/top_inset_padding.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import 'package:flutter/material.dart';

/// 顶部避让内边距:竖屏全屏时弹幕、播控顶部组件共用的统一 Padding。
/// [inset] 为 null 或 <= 0 时不加内边距,原样返回 child。
class TopInsetPadding extends StatelessWidget {
const TopInsetPadding({super.key, required this.inset, required this.child});

final double? inset;
final Widget child;

@override
Widget build(BuildContext context) {
final top = inset ?? 0;
return top > 0
? Padding(padding: EdgeInsets.only(top: top), child: child)
: child;
}
}
Loading