mod: 播放页样式
This commit is contained in:
@ -10,8 +10,10 @@ import 'package:pilipala/models/video/play/url.dart';
|
||||
import 'package:pilipala/models/video/reply/item.dart';
|
||||
import 'package:pilipala/pages/video/detail/replyReply/index.dart';
|
||||
|
||||
class VideoDetailController extends GetxController {
|
||||
class VideoDetailController extends GetxController
|
||||
with GetSingleTickerProviderStateMixin {
|
||||
int tabInitialIndex = 0;
|
||||
TabController? tabCtr;
|
||||
// tabs
|
||||
RxList<String> tabs = <String>['简介', '评论'].obs;
|
||||
|
||||
@ -63,6 +65,7 @@ class VideoDetailController extends GetxController {
|
||||
}
|
||||
heroTag = Get.arguments['heroTag'];
|
||||
}
|
||||
tabCtr = TabController(length: 2, vsync: this);
|
||||
queryVideoUrl();
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@ import 'package:pilipala/common/constants.dart';
|
||||
import 'package:pilipala/common/widgets/http_error.dart';
|
||||
import 'package:pilipala/pages/fav/index.dart';
|
||||
import 'package:pilipala/pages/favDetail/index.dart';
|
||||
import 'package:pilipala/pages/video/detail/index.dart';
|
||||
import 'package:pilipala/pages/video/detail/widgets/expandable_section.dart';
|
||||
import 'package:pilipala/common/widgets/network_img_layer.dart';
|
||||
import 'package:pilipala/common/widgets/stat/danmu.dart';
|
||||
@ -99,6 +100,7 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
|
||||
|
||||
final FavController _favController = Get.put(FavController());
|
||||
|
||||
late VideoDetailController? videoDetailCtr;
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
@ -110,6 +112,8 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
|
||||
);
|
||||
_manualAnimation =
|
||||
Tween<double>(begin: 0.5, end: 1.5).animate(_manualController!);
|
||||
videoDetailCtr =
|
||||
Get.find<VideoDetailController>(tag: Get.arguments['heroTag']);
|
||||
}
|
||||
|
||||
showFavBottomSheet() {
|
||||
@ -345,7 +349,7 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
// 点赞收藏转发
|
||||
_actionGrid(context, videoIntroController),
|
||||
_actionGrid(context, videoIntroController, videoDetailCtr),
|
||||
// 合集
|
||||
if (!widget.loadingStatus &&
|
||||
widget.videoDetail!.ugcSeason != null) ...[
|
||||
@ -425,39 +429,30 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
|
||||
}
|
||||
|
||||
// 喜欢 投币 分享
|
||||
Widget _actionGrid(BuildContext context, videoIntroController) {
|
||||
Widget _actionGrid(
|
||||
BuildContext context, videoIntroController, videoDetailCtr) {
|
||||
return LayoutBuilder(builder: (context, constraints) {
|
||||
return SizedBox(
|
||||
height: constraints.maxWidth / 5 * 0.8,
|
||||
child: Material(
|
||||
child: GridView.count(
|
||||
primary: false,
|
||||
padding: const EdgeInsets.all(0),
|
||||
crossAxisCount: 5,
|
||||
childAspectRatio: 1.25,
|
||||
children: <Widget>[
|
||||
// ActionItem(
|
||||
// icon: const Icon(FontAwesomeIcons.s),
|
||||
// selectIcon: const Icon(FontAwesomeIcons.s),
|
||||
// onTap: () => {},
|
||||
// selectStatus: true,
|
||||
// loadingStatus: false,
|
||||
// text: '三连',
|
||||
// InkWell(
|
||||
// onTap: () => videoIntroController.actionOneThree(),
|
||||
// borderRadius: StyleString.mdRadius,
|
||||
// child: Padding(
|
||||
// padding: const EdgeInsets.all(12),
|
||||
// child: Image.asset(
|
||||
// 'assets/images/logo/logo_big.png',
|
||||
// width: 10,
|
||||
// height: 10,
|
||||
// ),
|
||||
// ),
|
||||
// Column(
|
||||
// children: [],
|
||||
// ),
|
||||
InkWell(
|
||||
onTap: () => videoIntroController.actionOneThree(),
|
||||
borderRadius: StyleString.mdRadius,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(12),
|
||||
child: Image.asset(
|
||||
'assets/images/logo/logo_big.png',
|
||||
width: 10,
|
||||
height: 10,
|
||||
),
|
||||
),
|
||||
),
|
||||
Obx(
|
||||
() => ActionItem(
|
||||
icon: const Icon(FontAwesomeIcons.thumbsUp),
|
||||
@ -506,8 +501,19 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
|
||||
text: !widget.loadingStatus
|
||||
? widget.videoDetail!.stat!.share!.toString()
|
||||
: '-'),
|
||||
ActionItem(
|
||||
icon: const Icon(FontAwesomeIcons.comments),
|
||||
onTap: () {
|
||||
videoDetailCtr.tabCtr.animateTo(1);
|
||||
},
|
||||
selectStatus: false,
|
||||
loadingStatus: widget.loadingStatus,
|
||||
text: !widget.loadingStatus
|
||||
? widget.videoDetail!.stat!.reply!.toString()
|
||||
: '-'),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
@ -136,6 +136,7 @@ class _VideoReplyPanelState extends State<VideoReplyPanel>
|
||||
controller: _videoReplyController.scrollController,
|
||||
key: const PageStorageKey<String>('评论'),
|
||||
slivers: <Widget>[
|
||||
const SliverToBoxAdapter(child: SizedBox(height: 12)),
|
||||
FutureBuilder(
|
||||
future: _futureBuilderFuture,
|
||||
builder: (context, snapshot) {
|
||||
|
@ -1,4 +1,5 @@
|
||||
import 'dart:async';
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:extended_image/extended_image.dart';
|
||||
import 'package:extended_nested_scroll_view/extended_nested_scroll_view.dart';
|
||||
@ -144,17 +145,37 @@ class _VideoDetailPageState extends State<VideoDetailPage>
|
||||
final videoHeight = MediaQuery.of(context).size.width * 9 / 16;
|
||||
final double pinnedHeaderHeight =
|
||||
statusBarHeight + kToolbarHeight + videoHeight;
|
||||
return DefaultTabController(
|
||||
initialIndex: videoDetailController.tabInitialIndex,
|
||||
length: videoDetailController.tabs.length, // tab的数量.
|
||||
child: SafeArea(
|
||||
return SafeArea(
|
||||
top: false,
|
||||
bottom: false,
|
||||
child: Stack(
|
||||
children: [
|
||||
Positioned(
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
child: NetworkImgLayer(
|
||||
type: 'emote',
|
||||
src: videoDetailController.videoItem['pic'],
|
||||
width: Get.size.width,
|
||||
height: videoHeight + 100,
|
||||
),
|
||||
),
|
||||
Positioned.fill(
|
||||
child: BackdropFilter(
|
||||
filter: ImageFilter.blur(sigmaX: 100, sigmaY: 100), //可以看源码
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color:
|
||||
Theme.of(context).colorScheme.background.withOpacity(0.1),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Scaffold(
|
||||
resizeToAvoidBottomInset: false,
|
||||
key: videoDetailController.scaffoldKey,
|
||||
backgroundColor: Colors.transparent,
|
||||
body: ExtendedNestedScrollView(
|
||||
controller: _extendNestCtr,
|
||||
headerSliverBuilder:
|
||||
@ -167,8 +188,8 @@ class _VideoDetailPageState extends State<VideoDetailPage>
|
||||
scrolledUnderElevation: 0,
|
||||
forceElevated: innerBoxIsScrolled,
|
||||
expandedHeight: videoHeight,
|
||||
// collapsedHeight: videoHeight,
|
||||
backgroundColor: Theme.of(context).colorScheme.background,
|
||||
backgroundColor: Colors.transparent,
|
||||
// backgroundColor: Theme.of(context).colorScheme.background,
|
||||
flexibleSpace: FlexibleSpaceBar(
|
||||
background: Padding(
|
||||
padding: EdgeInsets.only(
|
||||
@ -177,8 +198,6 @@ class _VideoDetailPageState extends State<VideoDetailPage>
|
||||
builder: (context, boxConstraints) {
|
||||
double maxWidth = boxConstraints.maxWidth;
|
||||
double maxHeight = boxConstraints.maxHeight;
|
||||
// double PR =
|
||||
// MediaQuery.of(context).devicePixelRatio;
|
||||
return Hero(
|
||||
tag: videoDetailController.heroTag,
|
||||
child: Stack(
|
||||
@ -247,17 +266,18 @@ class _VideoDetailPageState extends State<VideoDetailPage>
|
||||
},
|
||||
pinnedHeaderSliverHeightBuilder: () {
|
||||
return playerStatus != PlayerStatus.playing
|
||||
? MediaQuery.of(context).padding.top + 50
|
||||
? statusBarHeight + kToolbarHeight
|
||||
: pinnedHeaderHeight;
|
||||
},
|
||||
onlyOneScrollInBody: true,
|
||||
body: Column(
|
||||
body: Container(
|
||||
color: Theme.of(context).colorScheme.background,
|
||||
child: Column(
|
||||
children: [
|
||||
Container(
|
||||
width: double.infinity,
|
||||
height: 45,
|
||||
height: 0,
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.background,
|
||||
border: Border(
|
||||
bottom: BorderSide(
|
||||
color:
|
||||
@ -274,7 +294,10 @@ class _VideoDetailPageState extends State<VideoDetailPage>
|
||||
margin: const EdgeInsets.only(left: 20),
|
||||
child: Obx(
|
||||
() => TabBar(
|
||||
controller: videoDetailController.tabCtr,
|
||||
dividerColor: Colors.transparent,
|
||||
indicatorColor:
|
||||
Theme.of(context).colorScheme.background,
|
||||
tabs: videoDetailController.tabs
|
||||
.map((String name) => Tab(text: name))
|
||||
.toList(),
|
||||
@ -294,6 +317,7 @@ class _VideoDetailPageState extends State<VideoDetailPage>
|
||||
),
|
||||
Expanded(
|
||||
child: TabBarView(
|
||||
controller: videoDetailController.tabCtr,
|
||||
children: [
|
||||
Builder(
|
||||
builder: (context) {
|
||||
@ -314,19 +338,20 @@ class _VideoDetailPageState extends State<VideoDetailPage>
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
// 播放完成/暂停播放
|
||||
Positioned(
|
||||
top: -MediaQuery.of(context).padding.top +
|
||||
(doubleOffset / videoHeight) * 50,
|
||||
top: -statusBarHeight +
|
||||
(doubleOffset / (videoHeight - kToolbarHeight)) *
|
||||
(kToolbarHeight - 9),
|
||||
left: 0,
|
||||
right: 0,
|
||||
child: Opacity(
|
||||
opacity: doubleOffset / videoHeight,
|
||||
opacity: doubleOffset / (videoHeight - kToolbarHeight),
|
||||
child: Container(
|
||||
height: 50 + MediaQuery.of(context).padding.top,
|
||||
height: statusBarHeight + kToolbarHeight,
|
||||
color: Theme.of(context).colorScheme.background,
|
||||
padding:
|
||||
EdgeInsets.only(top: MediaQuery.of(context).padding.top),
|
||||
padding: EdgeInsets.only(top: statusBarHeight),
|
||||
child: AppBar(
|
||||
primary: false,
|
||||
elevation: 0,
|
||||
@ -363,7 +388,6 @@ class _VideoDetailPageState extends State<VideoDetailPage>
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user