mod: 详情页横屏布局(bug很多不要下载!)

This commit is contained in:
orz12
2024-02-08 23:29:42 +08:00
parent 88bc9e3ff9
commit 2ed7d00483
17 changed files with 294 additions and 102 deletions

View File

@@ -2,7 +2,6 @@ import 'package:flutter/material.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:get/get.dart';
import 'package:hive/hive.dart';
import 'package:pilipala/common/constants.dart';
import 'package:pilipala/common/widgets/badge.dart';
import 'package:pilipala/common/widgets/network_img_layer.dart';
@@ -15,7 +14,6 @@ import 'package:pilipala/pages/video/detail/introduction/widgets/action_item.dar
import 'package:pilipala/pages/video/detail/introduction/widgets/action_row_item.dart';
import 'package:pilipala/pages/video/detail/introduction/widgets/fav_panel.dart';
import 'package:pilipala/utils/feed_back.dart';
import 'package:pilipala/utils/storage.dart';
import 'controller.dart';
import 'widgets/intro_detail.dart';
@@ -116,9 +114,7 @@ class _BangumiInfoState extends State<BangumiInfo> {
String heroTag = Get.arguments['heroTag'];
late final BangumiIntroController bangumiIntroController;
late final VideoDetailController videoDetailCtr;
Box localCache = GStrorage.localCache;
late final BangumiInfoModel? bangumiItem;
late double sheetHeight;
int? cid;
bool isProcessing = false;
void Function()? handleState(Future Function() action) {
@@ -137,7 +133,6 @@ class _BangumiInfoState extends State<BangumiInfo> {
bangumiIntroController = Get.put(BangumiIntroController(), tag: heroTag);
videoDetailCtr = Get.find<VideoDetailController>(tag: heroTag);
bangumiItem = bangumiIntroController.bangumiItem;
sheetHeight = localCache.get('sheetHeight');
cid = widget.cid!;
print('cid: $cid');
videoDetailCtr.cid.listen((p0) {
@@ -369,7 +364,6 @@ class _BangumiInfoState extends State<BangumiInfo> {
(bangumiItem != null
? bangumiItem!.episodes!.first.cid
: widget.bangumiDetail!.episodes!.first.cid),
sheetHeight: sheetHeight,
changeFuc: (bvid, cid, aid) => bangumiIntroController
.changeSeasonOrbangu(bvid, cid, aid),
)

View File

@@ -1,11 +1,8 @@
import 'package:flutter/material.dart';
import 'package:hive/hive.dart';
import 'package:get/get.dart';
import 'package:pilipala/common/widgets/stat/danmu.dart';
import 'package:pilipala/common/widgets/stat/view.dart';
import 'package:pilipala/utils/storage.dart';
Box localCache = GStrorage.localCache;
late double sheetHeight;
class IntroDetail extends StatelessWidget {
final dynamic bangumiDetail;
@@ -17,7 +14,6 @@ class IntroDetail extends StatelessWidget {
@override
Widget build(BuildContext context) {
sheetHeight = localCache.get('sheetHeight');
TextStyle smallTitle = TextStyle(
fontSize: 12,
color: Theme.of(context).colorScheme.onBackground,
@@ -25,7 +21,7 @@ class IntroDetail extends StatelessWidget {
return Container(
color: Theme.of(context).colorScheme.background,
padding: const EdgeInsets.only(left: 14, right: 14),
height: sheetHeight,
height: context.height.abs() * 0.7,
child: Column(
children: [
Container(

View File

@@ -12,13 +12,11 @@ class BangumiPanel extends StatefulWidget {
super.key,
required this.pages,
this.cid,
this.sheetHeight,
this.changeFuc,
});
final List<EpisodeItem> pages;
final int? cid;
final double? sheetHeight;
final Function? changeFuc;
@override
@@ -80,7 +78,7 @@ class _BangumiPanelState extends State<BangumiPanel> {
});
// 在这里使用 setState 更新状态
return Container(
height: widget.sheetHeight,
height: context.height.abs() * 0.7,
color: Theme.of(context).colorScheme.background,
child: Column(
children: [

View File

@@ -89,10 +89,6 @@ class _MainAppState extends State<MainApp> with SingleTickerProviderStateMixin {
Widget build(BuildContext context) {
Box localCache = GStrorage.localCache;
double statusBarHeight = MediaQuery.of(context).padding.top;
double sheetHeight = MediaQuery.sizeOf(context).height -
MediaQuery.of(context).padding.top -
MediaQuery.sizeOf(context).width * 9 / 16;
localCache.put('sheetHeight', sheetHeight);
localCache.put('statusBarHeight', statusBarHeight);
return PopScope(
canPop: false,

View File

@@ -241,6 +241,10 @@ class VideoDetailController extends GetxController
plPlayerController.headerControl = headerControl;
}
void setTriggerFullScreenCallback(void Function({bool? status}) callback) {
plPlayerController.setTriggerFullscreenCallback(callback);
}
// 视频链接
Future queryVideoUrl() async {
var result = await VideoHttp.videoUrl(cid: cid.value, bvid: bvid);
@@ -359,7 +363,7 @@ class VideoDetailController extends GetxController
if (result['code'] == -404) {
isShowCover.value = false;
}
if (result['code'] == 87008){
if (result['code'] == 87008) {
SmartDialog.showToast("当前视频可能是专属视频,可能需包月充电观看(${result['msg']})");
} else {
SmartDialog.showToast("错误(${result['code']}${result['msg']}");

View File

@@ -123,9 +123,7 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
late final VideoDetailController videoDetailCtr;
late final Map<dynamic, dynamic> videoItem;
final Box<dynamic> localCache = GStrorage.localCache;
final Box<dynamic> setting = GStrorage.setting;
late double sheetHeight;
late final bool loadingStatus; // 加载状态
@@ -153,7 +151,6 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
videoIntroController = Get.put(VideoIntroController(), tag: heroTag);
videoDetailCtr = Get.find<VideoDetailController>(tag: heroTag);
videoItem = videoIntroController.videoItem!;
sheetHeight = localCache.get('sheetHeight');
loadingStatus = widget.loadingStatus;
owner = loadingStatus ? videoItem['owner'] : widget.videoDetail!.owner;
@@ -381,7 +378,6 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
cid: videoIntroController.lastPlayCid.value != 0
? videoIntroController.lastPlayCid.value
: widget.videoDetail!.pages!.first.cid,
sheetHeight: sheetHeight,
changeFuc: (bvid, cid, aid) => videoIntroController
.changeSeasonOrbangu(bvid, cid, aid),
),
@@ -393,7 +389,6 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
Obx(() => PagesPanel(
pages: widget.videoDetail!.pages!,
cid: videoIntroController.lastPlayCid.value,
sheetHeight: sheetHeight,
changeFuc: (cid) =>
videoIntroController.changeSeasonOrbangu(
videoIntroController.bvid, cid, null),

View File

@@ -1,9 +1,7 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:hive/hive.dart';
import 'package:pilipala/common/widgets/http_error.dart';
import 'package:pilipala/utils/feed_back.dart';
import 'package:pilipala/utils/storage.dart';
class FavPanel extends StatefulWidget {
const FavPanel({super.key, this.ctr});
@@ -14,21 +12,18 @@ class FavPanel extends StatefulWidget {
}
class _FavPanelState extends State<FavPanel> {
final Box<dynamic> localCache = GStrorage.localCache;
late double sheetHeight;
late Future _futureBuilderFuture;
@override
void initState() {
super.initState();
sheetHeight = localCache.get('sheetHeight');
_futureBuilderFuture = widget.ctr!.queryVideoInFolder();
}
@override
Widget build(BuildContext context) {
return Container(
height: sheetHeight,
height: context.height.abs() * 0.7,
color: Theme.of(context).colorScheme.background,
child: Column(
children: [

View File

@@ -1,12 +1,10 @@
import 'package:flutter/material.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart';
import 'package:hive/hive.dart';
import 'package:pilipala/common/widgets/http_error.dart';
import 'package:pilipala/http/member.dart';
import 'package:pilipala/models/member/tags.dart';
import 'package:pilipala/utils/feed_back.dart';
import 'package:pilipala/utils/storage.dart';
class GroupPanel extends StatefulWidget {
final int? mid;
@@ -17,8 +15,6 @@ class GroupPanel extends StatefulWidget {
}
class _GroupPanelState extends State<GroupPanel> {
final Box<dynamic> localCache = GStrorage.localCache;
late double sheetHeight;
late Future _futureBuilderFuture;
late List<MemberTagItemModel> tagsList;
bool showDefault = true;
@@ -26,7 +22,6 @@ class _GroupPanelState extends State<GroupPanel> {
@override
void initState() {
super.initState();
sheetHeight = localCache.get('sheetHeight');
_futureBuilderFuture = MemberHttp.followUpTags();
}
@@ -56,7 +51,7 @@ class _GroupPanelState extends State<GroupPanel> {
@override
Widget build(BuildContext context) {
return Container(
height: sheetHeight,
height: context.height.abs() * 0.7,
color: Theme.of(context).colorScheme.background,
child: Column(
children: <Widget>[

View File

@@ -2,15 +2,10 @@ import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart';
import 'package:hive/hive.dart';
import 'package:pilipala/common/widgets/stat/danmu.dart';
import 'package:pilipala/common/widgets/stat/view.dart';
import 'package:pilipala/utils/storage.dart';
import 'package:pilipala/utils/utils.dart';
Box localCache = GStrorage.localCache;
late double sheetHeight;
class IntroDetail extends StatelessWidget {
const IntroDetail({
super.key,
@@ -20,11 +15,10 @@ class IntroDetail extends StatelessWidget {
@override
Widget build(BuildContext context) {
sheetHeight = localCache.get('sheetHeight');
return Container(
color: Theme.of(context).colorScheme.background,
padding: const EdgeInsets.only(left: 14, right: 14),
height: sheetHeight,
height: context.height.abs() * 0.7,
child: Column(
children: [
InkWell(

View File

@@ -8,12 +8,10 @@ class PagesPanel extends StatefulWidget {
super.key,
required this.pages,
this.cid,
this.sheetHeight,
this.changeFuc,
});
final List<Part> pages;
final int? cid;
final double? sheetHeight;
final Function? changeFuc;
@override
@@ -96,7 +94,7 @@ class _PagesPanelState extends State<PagesPanel> {
_scrollController.jumpTo(currentIndex * 56);
});
return Container(
height: widget.sheetHeight,
height: context.height.abs() * 0.7,
color: Theme.of(context).colorScheme.background,
child: Column(
children: [

View File

@@ -10,12 +10,10 @@ class SeasonPanel extends StatefulWidget {
super.key,
required this.ugcSeason,
this.cid,
this.sheetHeight,
this.changeFuc,
});
final UgcSeason ugcSeason;
final int? cid;
final double? sheetHeight;
final Function? changeFuc;
@override
@@ -104,7 +102,7 @@ class _SeasonPanelState extends State<SeasonPanel> {
itemScrollController.jumpTo(index: currentIndex);
});
return Container(
height: widget.sheetHeight,
height: context.height.abs() * 0.7,
color: Theme.of(context).colorScheme.background,
child: Column(
children: [

View File

@@ -1,13 +1,11 @@
import 'package:easy_debounce/easy_throttle.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:hive/hive.dart';
import 'package:pilipala/common/skeleton/video_reply.dart';
import 'package:pilipala/common/widgets/http_error.dart';
import 'package:pilipala/models/common/reply_type.dart';
import 'package:pilipala/models/video/reply/item.dart';
import 'package:pilipala/pages/video/detail/reply/widgets/reply_item.dart';
import 'package:pilipala/utils/storage.dart';
import 'controller.dart';
@@ -35,8 +33,6 @@ class VideoReplyReplyPanel extends StatefulWidget {
class _VideoReplyReplyPanelState extends State<VideoReplyReplyPanel> {
late VideoReplyReplyController _videoReplyReplyController;
late AnimationController replyAnimationCtl;
final Box<dynamic> localCache = GStrorage.localCache;
late double sheetHeight;
Future? _futureBuilderFuture;
late ScrollController scrollController;
@@ -61,7 +57,6 @@ class _VideoReplyReplyPanelState extends State<VideoReplyReplyPanel> {
},
);
sheetHeight = localCache.get('sheetHeight');
_futureBuilderFuture = _videoReplyReplyController.queryReplyList();
}
@@ -76,7 +71,7 @@ class _VideoReplyReplyPanelState extends State<VideoReplyReplyPanel> {
@override
Widget build(BuildContext context) {
return Container(
height: widget.source == 'videoDetail' ? sheetHeight : null,
height: widget.source == 'videoDetail' ? context.height.abs() * 0.7 : null,
color: Theme.of(context).colorScheme.background,
child: Column(
children: [

View File

@@ -63,6 +63,7 @@ class _VideoDetailPageState extends State<VideoDetailPage>
// 生命周期监听
late final AppLifecycleListener _lifecycleListener;
bool isShowing = true;
bool isFullScreen = false;
@override
void initState() {
@@ -91,7 +92,8 @@ class _VideoDetailPageState extends State<VideoDetailPage>
autoPlayEnable =
setting.get(SettingBoxKey.autoPlayEnable, defaultValue: true);
autoPiP = setting.get(SettingBoxKey.autoPiP, defaultValue: false);
videoDetailController
.setTriggerFullScreenCallback(triggerFullScreenCallback);
videoSourceInit();
appbarStreamListen();
lifecycleListener();
@@ -163,6 +165,8 @@ class _VideoDetailPageState extends State<VideoDetailPage>
/// 未开启自动播放时触发播放
Future<void> handlePlay() async {
videoDetailController
.setTriggerFullScreenCallback(triggerFullScreenCallback);
await videoDetailController.playerInit();
plPlayerController = videoDetailController.plPlayerController;
plPlayerController!.addStatusLister(playerListener);
@@ -231,6 +235,8 @@ class _VideoDetailPageState extends State<VideoDetailPage>
setState(() => isShowing = true);
videoDetailController.isFirstTime = false;
final bool autoplay = autoPlayEnable;
videoDetailController
.setTriggerFullScreenCallback(triggerFullScreenCallback);
videoDetailController.playerInit(autoplay: autoplay);
/// 未开启自动播放时,未播放跳转下一页返回/播放后跳转下一页返回
@@ -279,6 +285,13 @@ class _VideoDetailPageState extends State<VideoDetailPage>
}
}
void triggerFullScreenCallback({bool? status}) {
SmartDialog.showToast('triggerFullScreen $status $isFullScreen');
setState(() {
isFullScreen = status ?? !isFullScreen;
});
}
@override
Widget build(BuildContext context) {
final double videoHeight = MediaQuery.sizeOf(context).width * 9 / 16;
@@ -286,11 +299,11 @@ class _VideoDetailPageState extends State<VideoDetailPage>
statusBarHeight + kToolbarHeight + videoHeight;
Widget childWhenDisabled = SafeArea(
top: MediaQuery.of(context).orientation == Orientation.portrait &&
plPlayerController?.isFullScreen.value == true,
isFullScreen == true,
bottom: MediaQuery.of(context).orientation == Orientation.portrait &&
plPlayerController?.isFullScreen.value == true,
left: false, //plPlayerController?.isFullScreen.value != true,
right: false, //plPlayerController?.isFullScreen.value != true,
isFullScreen == true,
left: false, //isFullScreen != true,
right: false, //isFullScreen != true,
child: Stack(
children: [
Scaffold(
@@ -313,7 +326,7 @@ class _VideoDetailPageState extends State<VideoDetailPage>
() {
if (MediaQuery.of(context).orientation ==
Orientation.landscape ||
plPlayerController?.isFullScreen.value == true) {
isFullScreen == true) {
enterFullScreen();
} else {
exitFullScreen();
@@ -329,7 +342,7 @@ class _VideoDetailPageState extends State<VideoDetailPage>
forceElevated: innerBoxIsScrolled,
expandedHeight: MediaQuery.of(context).orientation ==
Orientation.landscape ||
plPlayerController?.isFullScreen.value == true
isFullScreen == true
? MediaQuery.sizeOf(context).height -
(MediaQuery.of(context).orientation ==
Orientation.landscape
@@ -339,11 +352,9 @@ class _VideoDetailPageState extends State<VideoDetailPage>
backgroundColor: Colors.black,
flexibleSpace: FlexibleSpaceBar(
background: PopScope(
canPop: plPlayerController?.isFullScreen.value !=
true,
canPop: isFullScreen != true,
onPopInvoked: (bool didPop) {
if (plPlayerController?.isFullScreen.value ==
true) {
if (isFullScreen == true) {
plPlayerController!
.triggerFullScreen(status: false);
}
@@ -501,9 +512,12 @@ class _VideoDetailPageState extends State<VideoDetailPage>
// },
/// 不收回
pinnedHeaderSliverHeightBuilder: () {
if (playerStatus != PlayerStatus.playing) {
return 0;
}
return MediaQuery.of(context).orientation ==
Orientation.landscape ||
plPlayerController?.isFullScreen.value == true
isFullScreen == true
? MediaQuery.sizeOf(context).height
: pinnedHeaderHeight;
},
@@ -603,6 +617,213 @@ class _VideoDetailPageState extends State<VideoDetailPage>
],
),
);
Widget childWhenDisabledLandscape = SafeArea(
left: isFullScreen != true,
right: isFullScreen != true,
child: Stack(children: [
Scaffold(
resizeToAvoidBottomInset: false,
key: videoDetailController.scaffoldKey,
backgroundColor: Theme.of(context).colorScheme.background,
appBar: PreferredSize(
preferredSize: const Size.fromHeight(0),
child: AppBar(
backgroundColor: Colors.transparent,
elevation: 0,
),
),
body: Row(
children: [
Column(
children: [
SizedBox(
width: isFullScreen == true
? Get.width
: Get.height * 0.6 * 16 / 9,
height: isFullScreen == true
? Get.height
: Get.height * 0.6,
child: PopScope(
canPop: isFullScreen != true,
onPopInvoked: (bool didPop) {
if (isFullScreen == true) {
plPlayerController!
.triggerFullScreen(status: false);
}
if (MediaQuery.of(context).orientation ==
Orientation.landscape &&
exitFullscreenAutoVertical) {
verticalScreen();
}
},
child: LayoutBuilder(
builder: (BuildContext context,
BoxConstraints boxConstraints) {
final double maxWidth =
boxConstraints.maxWidth / 2;
final double maxHeight =
boxConstraints.maxHeight / 2;
return Stack(
children: <Widget>[
if (isShowing)
Obx(
() => !videoDetailController
.autoPlay.value ||
plPlayerController
?.videoController ==
null
? nil
: PLVideoPlayer(
controller:
plPlayerController!,
headerControl:
videoDetailController
.headerControl,
danmuWidget: Obx(
() => PlDanmaku(
key: Key(
videoDetailController
.danmakuCid.value
.toString()),
cid: videoDetailController
.danmakuCid.value,
playerController:
plPlayerController!,
),
),
),
),
/// 关闭自动播放时 手动播放
if (!videoDetailController
.autoPlay.value) ...<Widget>[
Obx(
() => Visibility(
visible: videoDetailController
.isShowCover.value,
child: Positioned(
top: 0,
left: 0,
right: 0,
child: GestureDetector(
onTap: () {
handlePlay();
},
child: NetworkImgLayer(
type: 'emote',
src: videoDetailController
.videoItem['pic'],
width: maxWidth,
height: maxHeight,
),
),
),
),
),
Obx(
() => Visibility(
visible: videoDetailController
.isShowCover.value &&
videoDetailController
.isEffective.value,
child: Stack(
children: [
Positioned(
top: 0,
left: 0,
right: 0,
child: AppBar(
primary: false,
foregroundColor:
Colors.white,
elevation: 0,
scrolledUnderElevation: 0,
backgroundColor:
Colors.transparent,
actions: [
IconButton(
tooltip: '稍后再看',
onPressed: () async {
var res = await UserHttp
.toViewLater(
bvid: videoDetailController
.bvid);
SmartDialog
.showToast(
res['msg']);
},
icon: const Icon(Icons
.history_outlined),
),
const SizedBox(
width: 14)
],
),
),
Positioned(
right: 12,
bottom: 10,
child: IconButton(
tooltip: '播放',
onPressed: () =>
handlePlay(),
icon: Image.asset(
'assets/images/play.png',
width: 60,
height: 60,
)),
),
],
)),
),
]
],
);
},
))),
SizedBox(
width: isFullScreen == true
? Get.width
: Get.height * 0.6 * 16 / 9,
height: isFullScreen == true ? 0 : Get.height * 0.4,
child: (videoDetailController.videoType ==
SearchType.video)
? const CustomScrollView(
slivers: [VideoIntroPanel()])
: (videoDetailController.videoType ==
SearchType.media_bangumi)
? Obx(() => BangumiIntroPanel(
cid: videoDetailController.cid.value))
: const SizedBox(),
)
],
),
SizedBox(
width: isFullScreen == true
? 0
: (Get.width -
MediaQuery.of(context).padding.left -
MediaQuery.of(context).padding.right -
Get.height * 0.6 * 16 / 9),
height: Get.height,
child: TabBarView(
controller: videoDetailController.tabCtr,
children: <Widget>[
CustomScrollView(
slivers: [
RelatedVideoPanel(),
],
),
VideoReplyPanel(
bvid: videoDetailController.bvid,
)
],
),
)
],
))
]));
Widget childWhenEnabled = FutureBuilder(
key: Key(heroTag),
future: _futureBuilderFuture,
@@ -632,14 +853,25 @@ class _VideoDetailPageState extends State<VideoDetailPage>
}
},
);
if (Platform.isAndroid) {
return PiPSwitcher(
childWhenDisabled: childWhenDisabled,
childWhenEnabled: childWhenEnabled,
floating: floating,
);
} else {
return childWhenDisabled;
}
return OrientationBuilder(
builder: (BuildContext context, Orientation orientation) {
print("orientation:$orientation");
if (orientation == Orientation.portrait || isFullScreen == true) {
// 竖屏
return childWhenDisabled;
} else {
enterFullScreen();
return childWhenDisabledLandscape;
}
});
// if (Platform.isAndroid) {
// return PiPSwitcher(
// childWhenDisabled: childWhenDisabled,
// childWhenEnabled: childWhenEnabled,
// floating: floating,
// );
// } else {
// return childWhenDisabled;
// }
}
}

View File

@@ -2,14 +2,10 @@ import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart';
import 'package:hive/hive.dart';
import 'package:pilipala/models/video/ai.dart';
import 'package:pilipala/pages/video/detail/index.dart';
import 'package:pilipala/utils/storage.dart';
import 'package:pilipala/utils/utils.dart';
Box localCache = GStrorage.localCache;
late double sheetHeight;
class AiDetail extends StatelessWidget {
final ModelResult? modelResult;
@@ -21,11 +17,10 @@ class AiDetail extends StatelessWidget {
@override
Widget build(BuildContext context) {
sheetHeight = localCache.get('sheetHeight');
return Container(
color: Theme.of(context).colorScheme.background,
padding: const EdgeInsets.only(left: 14, right: 14),
height: sheetHeight,
height: context.height.abs() * 0.7,
child: Column(
children: [
InkWell(

View File

@@ -31,6 +31,7 @@ Box localCache = GStrorage.localCache;
class PlPlayerController {
Player? _videoPlayerController;
VideoController? _videoController;
void Function({bool? status})? triggerFullscreenCallback;
// 添加一个私有静态变量来保存实例
static PlPlayerController? _instance;
@@ -232,6 +233,11 @@ class PlPlayerController {
// 播放顺序相关
PlayRepeat playRepeat = PlayRepeat.pause;
void setTriggerFullscreenCallback(
void Function({bool? status}) triggerFullscreenCallback) {
this.triggerFullscreenCallback = triggerFullscreenCallback;
}
void updateSliderPositionSecond() {
int newSecond = _sliderPosition.value.inSeconds;
if (sliderPositionSeconds.value != newSecond) {
@@ -1001,6 +1007,9 @@ class PlPlayerController {
}
toggleFullScreen(false);
}
if (triggerFullscreenCallback != null) {
triggerFullscreenCallback!(status: status);
}
}
void addPositionListener(Function(Duration position) listener) =>

View File

@@ -48,6 +48,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
late VideoController videoController;
final PLVideoPlayerController _ctr = Get.put(PLVideoPlayerController());
final GlobalKey _playerKey = GlobalKey();
// bool _mountSeekBackwardButton = false;
// bool _mountSeekForwardButton = false;
// bool _hideSeekBackwardButton = false;
@@ -72,7 +73,6 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
late int defaultBtmProgressBehavior;
late bool enableQuickDouble;
late bool enableBackgroundPlay;
late double screenWidth;
// 用于记录上一次全屏切换手势触发时间,避免误触
DateTime? lastFullScreenToggleTime;
@@ -116,7 +116,6 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
@override
void initState() {
super.initState();
screenWidth = Get.size.width;
animationController = AnimationController(
vsync: this, duration: const Duration(milliseconds: 300));
videoController = widget.controller.videoController!;
@@ -210,6 +209,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
);
return Stack(
fit: StackFit.passthrough,
key: _playerKey,
children: <Widget>[
Obx(
() => Video(
@@ -445,7 +445,8 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
if (_.videoType.value == 'live' || _.controlsLock.value) {
return;
}
final double totalWidth = MediaQuery.sizeOf(context).width;
RenderBox renderBox = _playerKey.currentContext!.findRenderObject() as RenderBox;
final double totalWidth = renderBox.size.width;
final double tapPosition = details.localPosition.dx;
final double sectionWidth = totalWidth / 3;
String type = 'left';
@@ -475,7 +476,8 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
// final double tapPosition = details.localPosition.dx;
final int curSliderPosition =
_.sliderPosition.value.inMilliseconds;
final double scale = 90000 / MediaQuery.sizeOf(context).width;
RenderBox renderBox = _playerKey.currentContext!.findRenderObject() as RenderBox;
final double scale = 90000 / renderBox.size.width;
final Duration pos = Duration(
milliseconds:
curSliderPosition + (details.delta.dx * scale).round());
@@ -494,7 +496,8 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
},
// 垂直方向 音量/亮度调节
onVerticalDragUpdate: (DragUpdateDetails details) async {
final double totalWidth = MediaQuery.sizeOf(context).width;
RenderBox renderBox = _playerKey.currentContext!.findRenderObject() as RenderBox;
final double totalWidth = renderBox.size.width;
final double tapPosition = details.localPosition.dx;
final double sectionWidth = totalWidth / 3;
final double delta = details.delta.dy;
@@ -510,10 +513,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
}
if (tapPosition < sectionWidth) {
// 左边区域 👈
final double level = (_.isFullScreen.value
? Get.size.height
: screenWidth * 9 / 16) *
3;
final double level = renderBox.size.height * 3;
final double brightness =
_ctr.brightnessValue.value - delta / level;
final double result = brightness.clamp(0.0, 1.0);
@@ -540,10 +540,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
_distance = dy;
} else {
// 右边区域 👈
final double level = (_.isFullScreen.value
? Get.size.height
: screenWidth * 9 / 16) *
0.5;
final double level = renderBox.size.height * 0.5;
if(lastVolume < 0) {
lastVolume = _ctr.volumeValue.value;
}
@@ -761,11 +758,12 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
)
: nil,
),
Expanded(
child: SizedBox(
width: MediaQuery.sizeOf(context).width / 4,
),
),
const Spacer(),
// Expanded(
// child: SizedBox(
// width: context.width / 4,
// ),
// ),
Expanded(
child: _ctr.mountSeekForwardButton.value
? TweenAnimationBuilder<double>(

View File

@@ -146,7 +146,7 @@ class BottomControl extends StatelessWidget implements PreferredSizeWidget {
size: 15,
color: Colors.white,
),
fuc: () => triggerFullScreen!(),
fuc: () => triggerFullScreen!(status: !_.isFullScreen.value),
),
),
],