Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
bggRGjQaUbCoE
2025-10-20 14:20:13 +08:00
parent 23272d285b
commit 12c0ed5baf
2 changed files with 289 additions and 300 deletions

View File

@@ -460,12 +460,14 @@ class _LiveRoomPageState extends State<LiveRoomPage>
final isFullScreen = this.isFullScreen; final isFullScreen = this.isFullScreen;
final bottomHeight = 70 + padding.bottom; final bottomHeight = 70 + padding.bottom;
final topPadding = padding.top + kToolbarHeight; final topPadding = padding.top + kToolbarHeight;
final videoHeight = maxHeight - bottomHeight - topPadding; final videoHeight = isFullScreen
? maxHeight - padding.top
: maxHeight - bottomHeight - topPadding;
return Stack( return Stack(
clipBehavior: Clip.none, clipBehavior: Clip.none,
children: [ children: [
Positioned.fill( Positioned.fill(
top: isFullScreen ? 0 : topPadding, top: isFullScreen ? padding.top : topPadding,
bottom: isFullScreen ? 0 : bottomHeight, bottom: isFullScreen ? 0 : bottomHeight,
child: videoPlayerPanel( child: videoPlayerPanel(
width: maxWidth, width: maxWidth,

View File

@@ -551,330 +551,317 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
return Obx( return Obx(
() { () {
final isFullScreen = this.isFullScreen; final isFullScreen = this.isFullScreen;
return Padding( return Scaffold(
padding: EdgeInsets.only( resizeToAvoidBottomInset: false,
top: isFullScreen && isPortrait ? padding.top : 0, appBar: PreferredSize(
), preferredSize: const Size.fromHeight(0),
child: Scaffold( child: Obx(
resizeToAvoidBottomInset: false, () {
appBar: isFullScreen final scrollRatio = videoDetailController.scrollRatio.value;
? null bool shouldShow =
: PreferredSize( scrollRatio != 0 &&
preferredSize: const Size.fromHeight(0), videoDetailController.scrollCtr.offset != 0 &&
child: Obx( isPortrait;
() { return Stack(
final scrollRatio = clipBehavior: Clip.none,
videoDetailController.scrollRatio.value; children: [
bool shouldShow = AppBar(
scrollRatio != 0 && backgroundColor: Colors.black,
videoDetailController.scrollCtr.offset != 0 && toolbarHeight: 0,
isPortrait; systemOverlayStyle: Platform.isAndroid
return Stack( ? shouldShow
clipBehavior: Clip.none, ? null
children: [ : SystemUiOverlayStyle(
AppBar( statusBarIconBrightness: Brightness.light,
backgroundColor: Colors.black, systemNavigationBarIconBrightness:
toolbarHeight: 0, themeData.brightness.reverse,
systemOverlayStyle: Platform.isAndroid )
? shouldShow : null,
? null
: SystemUiOverlayStyle(
statusBarIconBrightness:
Brightness.light,
systemNavigationBarIconBrightness:
themeData.brightness.reverse,
)
: null,
),
if (shouldShow)
AppBar(
backgroundColor: themeData.colorScheme.surface
.withValues(alpha: scrollRatio),
toolbarHeight: 0,
systemOverlayStyle: Platform.isAndroid
? SystemUiOverlayStyle(
statusBarIconBrightness:
themeData.brightness.reverse,
systemNavigationBarIconBrightness:
themeData.brightness.reverse,
)
: null,
),
],
);
},
), ),
), if (shouldShow)
body: ExtendedNestedScrollView( AppBar(
key: videoDetailController.scrollKey, backgroundColor: themeData.colorScheme.surface
controller: videoDetailController.scrollCtr, .withValues(
onlyOneScrollInBody: true, alpha: scrollRatio,
pinnedHeaderSliverHeightBuilder: () { ),
double pinnedHeight = this.isFullScreen || !isPortrait toolbarHeight: 0,
? maxHeight - (isPortrait ? padding.top : 0) systemOverlayStyle: Platform.isAndroid
: videoDetailController.isExpanding || ? SystemUiOverlayStyle(
videoDetailController.isCollapsing statusBarIconBrightness:
? animHeight themeData.brightness.reverse,
: videoDetailController.isCollapsing || systemNavigationBarIconBrightness:
plPlayerController?.playerStatus.status.value == themeData.brightness.reverse,
PlayerStatus.playing )
? videoDetailController.minVideoHeight : null,
: kToolbarHeight; ),
if (videoDetailController.isExpanding && ],
videoDetailController.animationController.value == 1) { );
videoDetailController.isExpanding = false;
WidgetsBinding.instance.addPostFrameCallback((_) {
videoDetailController.scrollRatio.value = 0;
refreshPage();
});
} else if (videoDetailController.isCollapsing &&
videoDetailController.animationController.value == 1) {
videoDetailController.isCollapsing = false;
WidgetsBinding.instance.addPostFrameCallback((_) {
refreshPage();
});
}
return pinnedHeight;
}, },
headerSliverBuilder: (context, innerBoxIsScrolled) { ),
final isFullScreen = this.isFullScreen; ),
final height = isFullScreen || !isPortrait body: ExtendedNestedScrollView(
? maxHeight - (isPortrait ? padding.top : 0) key: videoDetailController.scrollKey,
: videoDetailController.isExpanding || controller: videoDetailController.scrollCtr,
videoDetailController.isCollapsing onlyOneScrollInBody: true,
? animHeight pinnedHeaderSliverHeightBuilder: () {
: videoDetailController.videoHeight; double pinnedHeight = this.isFullScreen || !isPortrait
return [ ? maxHeight - (isPortrait ? padding.top : 0)
SliverAppBar( : videoDetailController.isExpanding ||
elevation: 0, videoDetailController.isCollapsing
scrolledUnderElevation: 0, ? animHeight
primary: false, : videoDetailController.isCollapsing ||
automaticallyImplyLeading: false, plPlayerController?.playerStatus.status.value ==
pinned: true, PlayerStatus.playing
expandedHeight: height, ? videoDetailController.minVideoHeight
flexibleSpace: Stack( : kToolbarHeight;
clipBehavior: Clip.none, if (videoDetailController.isExpanding &&
children: [ videoDetailController.animationController.value == 1) {
SizedBox( videoDetailController.isExpanding = false;
WidgetsBinding.instance.addPostFrameCallback((_) {
videoDetailController.scrollRatio.value = 0;
refreshPage();
});
} else if (videoDetailController.isCollapsing &&
videoDetailController.animationController.value == 1) {
videoDetailController.isCollapsing = false;
WidgetsBinding.instance.addPostFrameCallback((_) {
refreshPage();
});
}
return pinnedHeight;
},
headerSliverBuilder: (context, innerBoxIsScrolled) {
final height = isFullScreen || !isPortrait
? maxHeight - (isPortrait ? padding.top : 0)
: videoDetailController.isExpanding ||
videoDetailController.isCollapsing
? animHeight
: videoDetailController.videoHeight;
return [
SliverAppBar(
elevation: 0,
scrolledUnderElevation: 0,
primary: false,
automaticallyImplyLeading: false,
pinned: true,
expandedHeight: height,
flexibleSpace: Stack(
clipBehavior: Clip.none,
children: [
SizedBox(
width: maxWidth,
height: height,
child: videoPlayer(
width: maxWidth, width: maxWidth,
height: height, height: height,
child: videoPlayer(
width: maxWidth,
height: height,
),
), ),
Obx( ),
() { Obx(
Widget toolbar() => Opacity( () {
opacity: videoDetailController.scrollRatio.value, Widget toolbar() => Opacity(
child: Container( opacity: videoDetailController.scrollRatio.value,
color: themeData.colorScheme.surface, child: Container(
alignment: Alignment.topCenter, color: themeData.colorScheme.surface,
child: SizedBox( alignment: Alignment.topCenter,
height: kToolbarHeight, child: SizedBox(
child: Stack( height: kToolbarHeight,
clipBehavior: Clip.none, child: Stack(
children: [ clipBehavior: Clip.none,
Align( children: [
alignment: Alignment.centerLeft, Align(
child: Row( alignment: Alignment.centerLeft,
mainAxisSize: MainAxisSize.min, child: Row(
children: [ mainAxisSize: MainAxisSize.min,
SizedBox( children: [
width: 42, SizedBox(
height: 34, width: 42,
child: IconButton( height: 34,
tooltip: '返回', child: IconButton(
icon: Icon( tooltip: '返回',
FontAwesomeIcons.arrowLeft, icon: Icon(
size: 15, FontAwesomeIcons.arrowLeft,
color: themeData size: 15,
.colorScheme color: themeData
.onSurface, .colorScheme
), .onSurface,
onPressed: Get.back,
), ),
onPressed: Get.back,
), ),
SizedBox( ),
width: 42, SizedBox(
height: 34, width: 42,
child: IconButton( height: 34,
tooltip: '返回主页', child: IconButton(
icon: Icon( tooltip: '返回主页',
FontAwesomeIcons.house, icon: Icon(
size: 15, FontAwesomeIcons.house,
color: themeData size: 15,
.colorScheme color: themeData
.onSurface, .colorScheme
), .onSurface,
onPressed: () {
videoDetailController
.plPlayerController
..isCloseAll = true
..dispose();
Get.until(
(route) => route.isFirst,
);
},
), ),
onPressed: () {
videoDetailController
.plPlayerController
..isCloseAll = true
..dispose();
Get.until(
(route) => route.isFirst,
);
},
), ),
], ),
), ],
), ),
Center( ),
child: Row( Center(
mainAxisSize: MainAxisSize.min, child: Row(
children: [ mainAxisSize: MainAxisSize.min,
Icon( children: [
Icons.play_arrow_rounded, Icon(
Icons.play_arrow_rounded,
color:
themeData.colorScheme.primary,
),
Text(
'${videoDetailController.playedTime == null
? '立即'
: plPlayerController!.playerStatus.status.value == PlayerStatus.completed
? '重新'
: '继续'}播放',
style: TextStyle(
color: color:
themeData.colorScheme.primary, themeData.colorScheme.primary,
), ),
Text( ),
'${videoDetailController.playedTime == null ],
? '立即'
: plPlayerController!.playerStatus.status.value == PlayerStatus.completed
? '重新'
: '继续'}播放',
style: TextStyle(
color: themeData
.colorScheme
.primary,
),
),
],
),
), ),
Align( ),
alignment: Alignment.centerRight, Align(
child: alignment: Alignment.centerRight,
videoDetailController.playedTime == child:
null videoDetailController.playedTime ==
? _moreBtn( null
themeData.colorScheme.onSurface, ? _moreBtn(
) themeData.colorScheme.onSurface,
: SizedBox( )
width: 42, : SizedBox(
height: 34, width: 42,
child: IconButton( height: 34,
tooltip: "更多设置", child: IconButton(
style: const ButtonStyle( tooltip: "更多设置",
padding: style: const ButtonStyle(
WidgetStatePropertyAll( padding:
EdgeInsets.zero, WidgetStatePropertyAll(
), EdgeInsets.zero,
), ),
onPressed: () => ),
videoDetailController onPressed: () =>
.headerCtrKey videoDetailController
.currentState .headerCtrKey
?.showSettingSheet(), .currentState
icon: Icon( ?.showSettingSheet(),
Icons.more_vert_outlined, icon: Icon(
size: 19, Icons.more_vert_outlined,
color: themeData size: 19,
.colorScheme color: themeData
.onSurface, .colorScheme
), .onSurface,
), ),
), ),
), ),
], ),
), ],
), ),
), ),
); ),
return videoDetailController.scrollRatio.value == );
0 || return videoDetailController.scrollRatio.value == 0 ||
videoDetailController.scrollCtr.offset == videoDetailController.scrollCtr.offset == 0 ||
0 || !isPortrait
!isPortrait ? const SizedBox.shrink()
? const SizedBox.shrink() : Positioned.fill(
: Positioned.fill( bottom: -2,
bottom: -2, child: GestureDetector(
child: GestureDetector( onTap: () async {
onTap: () async { if (videoDetailController.isQuerying) {
if (videoDetailController.isQuerying) { if (kDebugMode) {
if (kDebugMode) { debugPrint(
debugPrint( 'handlePlay: querying',
'handlePlay: querying', );
);
}
return;
} }
if (videoDetailController.videoUrl == return;
null || }
videoDetailController.audioUrl == if (videoDetailController.videoUrl ==
null) { null ||
if (kDebugMode) { videoDetailController.audioUrl ==
debugPrint( null) {
'handlePlay: videoUrl/audioUrl not initialized', if (kDebugMode) {
); debugPrint(
} 'handlePlay: videoUrl/audioUrl not initialized',
videoDetailController.queryVideoUrl(); );
return;
} }
videoDetailController videoDetailController.queryVideoUrl();
.scrollRatio return;
.value = }
0; videoDetailController.scrollRatio.value =
if (plPlayerController == null || 0;
videoDetailController.playedTime == if (plPlayerController == null ||
null) { videoDetailController.playedTime ==
handlePlay(); null) {
} else { handlePlay();
if (plPlayerController! } else {
if (plPlayerController!
.videoPlayerController!
.state
.completed) {
await plPlayerController!
.videoPlayerController! .videoPlayerController!
.state .seek(Duration.zero);
.completed) { plPlayerController!
await plPlayerController! .videoPlayerController!
.videoPlayerController! .play();
.seek(Duration.zero); } else {
plPlayerController! plPlayerController!
.videoPlayerController! .videoPlayerController!
.play(); .playOrPause();
} else {
plPlayerController!
.videoPlayerController!
.playOrPause();
}
} }
}, }
behavior: HitTestBehavior.opaque, },
child: toolbar(), behavior: HitTestBehavior.opaque,
), child: toolbar(),
); ),
}, );
},
),
],
),
),
];
},
body: Scaffold(
key: videoDetailController.childKey,
resizeToAvoidBottomInset: false,
backgroundColor: Colors.transparent,
body: Column(
children: [
buildTabbar(onTap: videoDetailController.animToTop),
Expanded(
child: videoTabBarView(
controller: videoDetailController.tabCtr,
children: [
videoIntro(
isHorizontal: false,
needCtr: false,
isNested: true,
), ),
if (videoDetailController.showReply)
videoReplyPanel(isNested: true),
if (_shouldShowSeasonPanel) seasonPanel,
], ],
), ),
), ),
]; ],
},
body: Scaffold(
key: videoDetailController.childKey,
resizeToAvoidBottomInset: false,
backgroundColor: Colors.transparent,
body: Column(
children: [
buildTabbar(onTap: videoDetailController.animToTop),
Expanded(
child: videoTabBarView(
controller: videoDetailController.tabCtr,
children: [
videoIntro(
isHorizontal: false,
needCtr: false,
isNested: true,
),
if (videoDetailController.showReply)
videoReplyPanel(isNested: true),
if (_shouldShowSeasonPanel) seasonPanel,
],
),
),
],
),
), ),
), ),
), ),