fix: 播放页横屏适配修复

This commit is contained in:
orz12
2024-02-11 19:45:50 +08:00
parent 2ed7d00483
commit 0d1f73808f
16 changed files with 490 additions and 505 deletions

View File

@@ -3,6 +3,8 @@ import 'package:get/get.dart';
import 'package:pilipala/common/widgets/stat/danmu.dart';
import 'package:pilipala/common/widgets/stat/view.dart';
import '../../../../utils/utils.dart';
class IntroDetail extends StatelessWidget {
final dynamic bangumiDetail;
@@ -21,7 +23,7 @@ class IntroDetail extends StatelessWidget {
return Container(
color: Theme.of(context).colorScheme.background,
padding: const EdgeInsets.only(left: 14, right: 14),
height: context.height.abs() * 0.7,
height: Utils.getSheetHeight(context),
child: Column(
children: [
Container(

View File

@@ -7,6 +7,8 @@ import 'package:pilipala/pages/video/detail/index.dart';
import 'package:pilipala/utils/storage.dart';
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
import '../../../utils/utils.dart';
class BangumiPanel extends StatefulWidget {
const BangumiPanel({
super.key,
@@ -78,7 +80,7 @@ class _BangumiPanelState extends State<BangumiPanel> {
});
// 在这里使用 setState 更新状态
return Container(
height: context.height.abs() * 0.7,
height: Utils.getSheetHeight(context),
color: Theme.of(context).colorScheme.background,
child: Column(
children: [

View File

@@ -117,10 +117,10 @@ class _PlaySettingState extends State<PlaySetting> {
defaultVal: false,
),
const SetSwitchItem(
title: '恢复竖屏',
subTitle: '退出全屏视频时自动恢复竖屏,关闭可以保持横屏状态',
setKey: SettingBoxKey.exitFullscreenAutoVertical,
defaultVal: true,
title: '横屏适配(测试)',
subTitle: '开启该项在播放页启用横屏布局与逻辑',
setKey: SettingBoxKey.horizontalScreen,
defaultVal: false,
),
const SetSwitchItem(
title: '开启硬解',

View File

@@ -3,6 +3,8 @@ import 'package:get/get.dart';
import 'package:pilipala/common/widgets/http_error.dart';
import 'package:pilipala/utils/feed_back.dart';
import '../../../../../utils/utils.dart';
class FavPanel extends StatefulWidget {
const FavPanel({super.key, this.ctr});
final dynamic ctr;
@@ -23,7 +25,7 @@ class _FavPanelState extends State<FavPanel> {
@override
Widget build(BuildContext context) {
return Container(
height: context.height.abs() * 0.7,
height: Utils.getSheetHeight(context),
color: Theme.of(context).colorScheme.background,
child: Column(
children: [

View File

@@ -6,6 +6,8 @@ import 'package:pilipala/http/member.dart';
import 'package:pilipala/models/member/tags.dart';
import 'package:pilipala/utils/feed_back.dart';
import '../../../../../utils/utils.dart';
class GroupPanel extends StatefulWidget {
final int? mid;
const GroupPanel({super.key, this.mid});
@@ -51,7 +53,7 @@ class _GroupPanelState extends State<GroupPanel> {
@override
Widget build(BuildContext context) {
return Container(
height: context.height.abs() * 0.7,
height: Utils.getSheetHeight(context),
color: Theme.of(context).colorScheme.background,
child: Column(
children: <Widget>[

View File

@@ -18,7 +18,7 @@ class IntroDetail extends StatelessWidget {
return Container(
color: Theme.of(context).colorScheme.background,
padding: const EdgeInsets.only(left: 14, right: 14),
height: context.height.abs() * 0.7,
height: Utils.getSheetHeight(context),
child: Column(
children: [
InkWell(

View File

@@ -3,6 +3,8 @@ import 'package:get/get.dart';
import 'package:pilipala/models/video_detail_res.dart';
import 'package:pilipala/pages/video/detail/index.dart';
import '../../../../../utils/utils.dart';
class PagesPanel extends StatefulWidget {
const PagesPanel({
super.key,
@@ -94,7 +96,7 @@ class _PagesPanelState extends State<PagesPanel> {
_scrollController.jumpTo(currentIndex * 56);
});
return Container(
height: context.height.abs() * 0.7,
height: Utils.getSheetHeight(context),
color: Theme.of(context).colorScheme.background,
child: Column(
children: [

View File

@@ -5,6 +5,8 @@ import 'package:pilipala/pages/video/detail/index.dart';
import 'package:pilipala/utils/id_utils.dart';
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
import '../../../../../utils/utils.dart';
class SeasonPanel extends StatefulWidget {
const SeasonPanel({
super.key,
@@ -102,7 +104,7 @@ class _SeasonPanelState extends State<SeasonPanel> {
itemScrollController.jumpTo(index: currentIndex);
});
return Container(
height: context.height.abs() * 0.7,
height: Utils.getSheetHeight(context),
color: Theme.of(context).colorScheme.background,
child: Column(
children: [

View File

@@ -121,7 +121,7 @@ class _VideoReplyPanelState extends State<VideoReplyPanel>
void dispose() {
scrollController.removeListener(() {});
fabAnimationCtr.dispose();
scrollController.dispose();
// scrollController.dispose();
super.dispose();
}

View File

@@ -7,6 +7,7 @@ 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 '../../../../utils/utils.dart';
import 'controller.dart';
class VideoReplyReplyPanel extends StatefulWidget {
@@ -71,7 +72,7 @@ class _VideoReplyReplyPanelState extends State<VideoReplyReplyPanel> {
@override
Widget build(BuildContext context) {
return Container(
height: widget.source == 'videoDetail' ? context.height.abs() * 0.7 : null,
height: widget.source == 'videoDetail' ? Utils.getSheetHeight(context) : null,
color: Theme.of(context).colorScheme.background,
child: Column(
children: [

View File

@@ -57,13 +57,13 @@ class _VideoDetailPageState extends State<VideoDetailPage>
// 自动退出全屏
late bool autoExitFullcreen;
late bool autoPlayEnable;
late bool exitFullscreenAutoVertical;
late bool horizontalScreen;
late bool autoPiP;
final Floating floating = Floating();
// 生命周期监听
late final AppLifecycleListener _lifecycleListener;
bool isShowing = true;
bool isFullScreen = false;
RxBool isFullScreen = false.obs;
@override
void initState() {
@@ -87,8 +87,8 @@ class _VideoDetailPageState extends State<VideoDetailPage>
statusBarHeight = localCache.get('statusBarHeight');
autoExitFullcreen =
setting.get(SettingBoxKey.enableAutoExit, defaultValue: false);
exitFullscreenAutoVertical = setting
.get(SettingBoxKey.exitFullscreenAutoVertical, defaultValue: true);
horizontalScreen =
setting.get(SettingBoxKey.horizontalScreen, defaultValue: false);
autoPlayEnable =
setting.get(SettingBoxKey.autoPlayEnable, defaultValue: true);
autoPiP = setting.get(SettingBoxKey.autoPiP, defaultValue: false);
@@ -286,22 +286,19 @@ class _VideoDetailPageState extends State<VideoDetailPage>
}
void triggerFullScreenCallback({bool? status}) {
SmartDialog.showToast('triggerFullScreen $status $isFullScreen');
// SmartDialog.showToast('triggerFullScreen $status $isFullScreen.value');
setState(() {
isFullScreen = status ?? !isFullScreen;
isFullScreen.value = status ?? !isFullScreen.value;
});
}
@override
Widget build(BuildContext context) {
final double videoHeight = MediaQuery.sizeOf(context).width * 9 / 16;
final double pinnedHeaderHeight =
statusBarHeight + kToolbarHeight + videoHeight;
Widget childWhenDisabled = SafeArea(
top: MediaQuery.of(context).orientation == Orientation.portrait &&
isFullScreen == true,
isFullScreen.value == true,
bottom: MediaQuery.of(context).orientation == Orientation.portrait &&
isFullScreen == true,
isFullScreen.value == true,
left: false, //isFullScreen != true,
right: false, //isFullScreen != true,
child: Stack(
@@ -317,61 +314,44 @@ class _VideoDetailPageState extends State<VideoDetailPage>
elevation: 0,
),
),
body: ExtendedNestedScrollView(
controller: _extendNestCtr,
headerSliverBuilder:
(BuildContext context2, bool innerBoxIsScrolled) {
return <Widget>[
body: Column(
children: [
Obx(
() {
if (MediaQuery.of(context).orientation ==
Orientation.landscape ||
isFullScreen == true) {
isFullScreen.value == true) {
enterFullScreen();
} else {
exitFullScreen();
}
return SliverAppBar(
automaticallyImplyLeading: false,
// 假装使用一个非空变量避免Obx检测不到而罢工
pinned: videoDetailController.autoPlay.value ^
false ^
videoDetailController.autoPlay.value,
elevation: 0,
scrolledUnderElevation: 0,
forceElevated: innerBoxIsScrolled,
expandedHeight: MediaQuery.of(context).orientation ==
final double videoheight = Get.width * 9 / 16;
final double videowidth = Get.width;
return SizedBox(
height: MediaQuery.of(context).orientation ==
Orientation.landscape ||
isFullScreen == true
isFullScreen.value == true
? MediaQuery.sizeOf(context).height -
(MediaQuery.of(context).orientation ==
Orientation.landscape
? 0
: MediaQuery.of(context).padding.top)
: videoHeight,
backgroundColor: Colors.black,
flexibleSpace: FlexibleSpaceBar(
background: PopScope(
canPop: isFullScreen != true,
: videoheight,
width: MediaQuery.of(context).size.width,
child: PopScope(
canPop: isFullScreen.value != true,
onPopInvoked: (bool didPop) {
if (isFullScreen == true) {
if (isFullScreen.value == true) {
plPlayerController!
.triggerFullScreen(status: false);
}
if (MediaQuery.of(context).orientation ==
Orientation.landscape &&
exitFullscreenAutoVertical) {
!horizontalScreen) {
verticalScreen();
}
},
child: LayoutBuilder(
builder: (BuildContext context,
BoxConstraints boxConstraints) {
final double maxWidth =
boxConstraints.maxWidth;
final double maxHeight =
boxConstraints.maxHeight;
return Stack(
child: Stack(
children: <Widget>[
if (isShowing)
FutureBuilder(
@@ -381,9 +361,13 @@ class _VideoDetailPageState extends State<VideoDetailPage>
if (snapshot.hasData &&
snapshot.data['status']) {
return Obx(
() =>
!videoDetailController
.autoPlay.value
() => !videoDetailController
.autoPlay.value ||
plPlayerController ==
null ||
plPlayerController!
.videoController ==
null
? nil
: PLVideoPlayer(
controller:
@@ -393,11 +377,13 @@ class _VideoDetailPageState extends State<VideoDetailPage>
.headerControl,
danmuWidget: Obx(
() => PlDanmaku(
key: Key(videoDetailController
key: Key(
videoDetailController
.danmakuCid
.value
.toString()),
cid: videoDetailController
cid:
videoDetailController
.danmakuCid
.value,
playerController:
@@ -409,8 +395,7 @@ class _VideoDetailPageState extends State<VideoDetailPage>
} else {
return const SizedBox();
}
},
),
}),
/// 关闭自动播放时 手动播放
if (!videoDetailController
@@ -431,8 +416,8 @@ class _VideoDetailPageState extends State<VideoDetailPage>
type: 'emote',
src: videoDetailController
.videoItem['pic'],
width: maxWidth,
height: maxHeight,
width: videowidth,
height: videoheight,
),
),
),
@@ -452,8 +437,7 @@ class _VideoDetailPageState extends State<VideoDetailPage>
right: 0,
child: AppBar(
primary: false,
foregroundColor:
Colors.white,
foregroundColor: Colors.white,
elevation: 0,
scrolledUnderElevation: 0,
backgroundColor:
@@ -464,17 +448,16 @@ class _VideoDetailPageState extends State<VideoDetailPage>
onPressed: () async {
var res = await UserHttp
.toViewLater(
bvid: videoDetailController
bvid:
videoDetailController
.bvid);
SmartDialog
.showToast(
SmartDialog.showToast(
res['msg']);
},
icon: const Icon(Icons
.history_outlined),
icon: const Icon(
Icons.history_outlined),
),
const SizedBox(
width: 14)
const SizedBox(width: 14)
],
),
),
@@ -483,8 +466,7 @@ class _VideoDetailPageState extends State<VideoDetailPage>
bottom: 10,
child: IconButton(
tooltip: '播放',
onPressed: () =>
handlePlay(),
onPressed: () => handlePlay(),
icon: Image.asset(
'assets/images/play.png',
width: 60,
@@ -496,33 +478,21 @@ class _VideoDetailPageState extends State<VideoDetailPage>
),
]
],
);
},
)),
),
);
},
),
];
},
// pinnedHeaderSliverHeightBuilder: () {
// return playerStatus != PlayerStatus.playing
// ? statusBarHeight + kToolbarHeight
// : pinnedHeaderHeight;
// },
/// 不收回
pinnedHeaderSliverHeightBuilder: () {
if (playerStatus != PlayerStatus.playing) {
return 0;
}
return MediaQuery.of(context).orientation ==
SizedBox(
height: MediaQuery.of(context).orientation ==
Orientation.landscape ||
isFullScreen == true
? MediaQuery.sizeOf(context).height
: pinnedHeaderHeight;
},
onlyOneScrollInBody: true,
body: ColoredBox(
isFullScreen.value == true
? 0
: Get.height -
Get.width * 9 / 16 -
MediaQuery.of(context).padding.top -
MediaQuery.of(context).padding.bottom,
width: MediaQuery.of(context).size.width,
child: ColoredBox(
key: Key(heroTag),
color: Theme.of(context).colorScheme.background,
child: Column(
@@ -557,23 +527,13 @@ class _VideoDetailPageState extends State<VideoDetailPage>
if (videoDetailController.videoType ==
SearchType.video) ...[
const VideoIntroPanel(),
] else if (videoDetailController.videoType ==
] else if (videoDetailController
.videoType ==
SearchType.media_bangumi) ...[
Obx(() => BangumiIntroPanel(
cid: videoDetailController.cid.value)),
cid: videoDetailController
.cid.value)),
],
// if (videoDetailController.videoType ==
// SearchType.video) ...[
// SliverPersistentHeader(
// floating: true,
// pinned: true,
// delegate: SliverHeaderDelegate(
// height: 50,
// child:
// const MenuRow(loadingStatus: false),
// ),
// ),
// ],
SliverToBoxAdapter(
child: Divider(
indent: 12,
@@ -598,29 +558,15 @@ class _VideoDetailPageState extends State<VideoDetailPage>
),
),
),
),
/// 重新进入会刷新
// 播放完成/暂停播放
// StreamBuilder(
// stream: appbarStream.stream,
// initialData: 0,
// builder: ((context, snapshot) {
// return ScrollAppBar(
// snapshot.data!.toDouble(),
// () => continuePlay(),
// playerStatus,
// null,
// );
// }),
// )
],
)),
],
),
);
Widget childWhenDisabledLandscape = SafeArea(
left: isFullScreen != true,
right: isFullScreen != true,
left: isFullScreen.value != true,
right: isFullScreen.value != true,
child: Stack(children: [
Scaffold(
resizeToAvoidBottomInset: false,
@@ -633,45 +579,49 @@ class _VideoDetailPageState extends State<VideoDetailPage>
elevation: 0,
),
),
body: Row(
body: Obx(() {
final double videoheight = Get.height * 0.32 + Get.width * 0.13;
final double videowidth = videoheight * 16 / 9;
return Row(
children: [
Column(
children: [
SizedBox(
width: isFullScreen == true
width: isFullScreen.value == true
? Get.width
: Get.height * 0.6 * 16 / 9,
height: isFullScreen == true
: videowidth,
height: isFullScreen.value == true
? Get.height
: Get.height * 0.6,
: videoheight,
child: PopScope(
canPop: isFullScreen != true,
canPop: isFullScreen.value != true,
onPopInvoked: (bool didPop) {
if (isFullScreen == true) {
if (isFullScreen.value == true) {
plPlayerController!
.triggerFullScreen(status: false);
}
if (MediaQuery.of(context).orientation ==
Orientation.landscape &&
exitFullscreenAutoVertical) {
!horizontalScreen) {
verticalScreen();
}
},
child: LayoutBuilder(
builder: (BuildContext context,
BoxConstraints boxConstraints) {
final double maxWidth =
boxConstraints.maxWidth / 2;
final double maxHeight =
boxConstraints.maxHeight / 2;
return Stack(
child: Stack(
children: <Widget>[
if (isShowing)
Obx(
FutureBuilder(
future: _futureBuilderFuture,
builder: (BuildContext context,
AsyncSnapshot snapshot) {
if (snapshot.hasData &&
snapshot.data['status']) {
return Obx(
() => !videoDetailController
.autoPlay.value ||
plPlayerController
?.videoController ==
plPlayerController ==
null ||
plPlayerController!
.videoController ==
null
? nil
: PLVideoPlayer(
@@ -684,16 +634,23 @@ class _VideoDetailPageState extends State<VideoDetailPage>
() => PlDanmaku(
key: Key(
videoDetailController
.danmakuCid.value
.danmakuCid
.value
.toString()),
cid: videoDetailController
.danmakuCid.value,
cid:
videoDetailController
.danmakuCid
.value,
playerController:
plPlayerController!,
),
),
),
),
);
} else {
return const SizedBox();
}
}),
/// 关闭自动播放时 手动播放
if (!videoDetailController
@@ -714,8 +671,8 @@ class _VideoDetailPageState extends State<VideoDetailPage>
type: 'emote',
src: videoDetailController
.videoItem['pic'],
width: maxWidth,
height: maxHeight,
width: videowidth,
height: videoheight,
),
),
),
@@ -747,17 +704,16 @@ class _VideoDetailPageState extends State<VideoDetailPage>
onPressed: () async {
var res = await UserHttp
.toViewLater(
bvid: videoDetailController
bvid:
videoDetailController
.bvid);
SmartDialog
.showToast(
SmartDialog.showToast(
res['msg']);
},
icon: const Icon(Icons
.history_outlined),
),
const SizedBox(
width: 14)
const SizedBox(width: 14)
],
),
),
@@ -779,14 +735,14 @@ class _VideoDetailPageState extends State<VideoDetailPage>
),
]
],
);
},
))),
SizedBox(
width: isFullScreen == true
width: isFullScreen.value == true
? Get.width
: Get.height * 0.6 * 16 / 9,
height: isFullScreen == true ? 0 : Get.height * 0.4,
: videowidth,
height: isFullScreen.value == true
? 0
: Get.height - videoheight,
child: (videoDetailController.videoType ==
SearchType.video)
? const CustomScrollView(
@@ -800,12 +756,12 @@ class _VideoDetailPageState extends State<VideoDetailPage>
],
),
SizedBox(
width: isFullScreen == true
width: isFullScreen.value == true
? 0
: (Get.width -
MediaQuery.of(context).padding.left -
MediaQuery.of(context).padding.right -
Get.height * 0.6 * 16 / 9),
videowidth),
height: Get.height,
child: TabBarView(
controller: videoDetailController.tabCtr,
@@ -822,7 +778,8 @@ class _VideoDetailPageState extends State<VideoDetailPage>
),
)
],
))
);
}))
]));
Widget childWhenEnabled = FutureBuilder(
key: Key(heroTag),
@@ -855,23 +812,27 @@ class _VideoDetailPageState extends State<VideoDetailPage>
);
return OrientationBuilder(
builder: (BuildContext context, Orientation orientation) {
print("orientation:$orientation");
if (orientation == Orientation.portrait || isFullScreen == true) {
// 竖屏
return childWhenDisabled;
} else {
if (orientation == Orientation.landscape) {
enterFullScreen();
return childWhenDisabledLandscape;
}
if (Platform.isAndroid) {
return PiPSwitcher(
childWhenDisabled: Container(
key: UniqueKey(),
child: !horizontalScreen || orientation == Orientation.portrait
? childWhenDisabled
: childWhenDisabledLandscape,
),
childWhenEnabled: childWhenEnabled,
floating: floating,
);
}
return Container(
key: UniqueKey(),
child: !horizontalScreen || orientation == Orientation.portrait
? childWhenDisabled
: childWhenDisabledLandscape,
);
});
// if (Platform.isAndroid) {
// return PiPSwitcher(
// childWhenDisabled: childWhenDisabled,
// childWhenEnabled: childWhenEnabled,
// floating: floating,
// );
// } else {
// return childWhenDisabled;
// }
}
}

View File

@@ -20,7 +20,7 @@ class AiDetail extends StatelessWidget {
return Container(
color: Theme.of(context).colorScheme.background,
padding: const EdgeInsets.only(left: 14, right: 14),
height: context.height.abs() * 0.7,
height: Utils.getSheetHeight(context),
child: Column(
children: [
InkWell(

View File

@@ -1070,8 +1070,8 @@ class _HeaderControlState extends State<HeaderControl> {
<void>{
if (MediaQuery.of(context).orientation ==
Orientation.landscape &&
setting.get(SettingBoxKey.exitFullscreenAutoVertical,
defaultValue: true))
!setting.get(SettingBoxKey.horizontalScreen,
defaultValue: false))
{
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,

View File

@@ -1002,7 +1002,7 @@ class PlPlayerController {
StatusBarControl.setHidden(false, animation: StatusBarAnimation.FADE);
// Get.back();
exitFullScreen();
if (setting.get(SettingBoxKey.exitFullscreenAutoVertical, defaultValue: true)) {
if (!setting.get(SettingBoxKey.horizontalScreen, defaultValue: false)) {
await verticalScreen();
}
toggleFullScreen(false);

View File

@@ -92,7 +92,7 @@ class SettingBoxKey {
enableAutoBrightness = 'enableAutoBrightness',
enableAutoEnter = 'enableAutoEnter',
enableAutoExit = 'enableAutoExit',
exitFullscreenAutoVertical = 'exitFullscreenAutoVertical',
horizontalScreen = 'horizontalScreen',
p1080 = 'p1080',
enableCDN = 'enableCDN',
autoPiP = 'autoPiP',

View File

@@ -9,6 +9,7 @@ import 'package:crypto/crypto.dart';
import 'package:device_info_plus/device_info_plus.dart';
import 'package:flutter/material.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:path_provider/path_provider.dart';
import 'package:url_launcher/url_launcher.dart';
@@ -327,6 +328,16 @@ class Utils {
return '$formattedHours:$formattedMinutes';
}
static double getSheetHeight(BuildContext context) {
double height = context.height.abs();
double width = context.width.abs();
if (height > width) {
return height * 0.7;
}
//横屏状态
return height;
}
static String appSign(
Map<String, dynamic> params, String appkey, String appsec) {
params['appkey'] = appkey;