mod: merge tabbar from pilipala

This commit is contained in:
bggRGjQaUbCoE
2024-08-26 20:40:41 +08:00
parent 448d554f03
commit 50c911a6a6
4 changed files with 137 additions and 53 deletions

View File

@@ -1,3 +1,4 @@
import 'package:PiliPalaX/utils/extension.dart';
import 'package:easy_debounce/easy_throttle.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
@@ -26,7 +27,7 @@ class VideoReplyController extends GetxController {
String nextOffset = "";
bool isLoadingMore = false;
RxString noMore = ''.obs;
RxInt count = 0.obs;
RxInt count = (-1).obs;
// 当前回复的回复
ReplyItemModel? currentReplyItem;
@@ -77,7 +78,6 @@ class VideoReplyController extends GetxController {
if (res['data'].cursor.isEnd == true) {
noMore.value = '没有更多了';
}
} else {
// 未登录状态replies可能返回null
noMore.value = nextOffset == "" && type == 'init' ? '还没有评论' : '没有更多了';
@@ -126,4 +126,8 @@ class VideoReplyController extends GetxController {
queryReplyList(type: 'init');
});
}
void animToTop() {
scrollController.animToTop();
}
}

View File

@@ -57,9 +57,7 @@ class _VideoReplyPanelState extends State<VideoReplyPanel>
VideoReplyController(widget.oid, widget.rpid.toString(), replyLevel),
tag: widget.rpid.toString());
} else {
_videoReplyController = Get.put(
VideoReplyController(widget.oid, '', replyLevel),
tag: heroTag);
_videoReplyController = Get.find<VideoReplyController>(tag: heroTag);
}
fabAnimationCtr = AnimationController(
@@ -135,38 +133,20 @@ class _VideoReplyPanelState extends State<VideoReplyPanel>
key: const PageStorageKey<String>('评论'),
slivers: <Widget>[
SliverPersistentHeader(
pinned: true,
floating: false,
pinned: false,
floating: true,
delegate: _MySliverPersistentHeaderDelegate(
child: Container(
height: 45,
height: 40,
padding: const EdgeInsets.fromLTRB(12, 0, 6, 0),
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.background,
border: Border(
bottom: BorderSide(
color: Theme.of(context)
.colorScheme
.outline
.withOpacity(0.1)),
),
),
color: Theme.of(context).colorScheme.surface,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Obx(
() => AnimatedSwitcher(
duration: const Duration(milliseconds: 400),
transitionBuilder:
(Widget child, Animation<double> animation) {
return ScaleTransition(
scale: animation, child: child);
},
child: Text(
'${_videoReplyController.count.value}条回复',
key: ValueKey<int>(
_videoReplyController.count.value),
),
() => Text(
'${_videoReplyController.sortTypeLabel.value}评论',
style: const TextStyle(fontSize: 13),
),
),
SizedBox(
@@ -175,10 +155,12 @@ class _VideoReplyPanelState extends State<VideoReplyPanel>
onPressed: () =>
_videoReplyController.queryBySort(),
icon: const Icon(Icons.sort, size: 16),
label: Obx(() => Text(
_videoReplyController.sortTypeLabel.value,
style: const TextStyle(fontSize: 13),
)),
label: Obx(
() => Text(
_videoReplyController.sortTypeLabel.value,
style: const TextStyle(fontSize: 13),
),
),
),
)
],

View File

@@ -3,6 +3,7 @@ import 'dart:io';
import 'dart:math';
import 'dart:ui';
import 'package:PiliPalaX/utils/extension.dart';
import 'package:auto_orientation/auto_orientation.dart';
import 'package:floating/floating.dart';
import 'package:flutter/services.dart';
@@ -40,10 +41,12 @@ class VideoDetailPage extends StatefulWidget {
class _VideoDetailPageState extends State<VideoDetailPage>
with TickerProviderStateMixin, RouteAware {
late VideoDetailController videoDetailController;
late VideoReplyController _videoReplyController;
PlPlayerController? plPlayerController;
late StreamController<double> appbarStream;
late VideoIntroController videoIntroController;
late BangumiIntroController bangumiIntroController;
late final _introController = ScrollController();
late String heroTag;
PlayerStatus playerStatus = PlayerStatus.playing;
@@ -77,6 +80,9 @@ class _VideoDetailPageState extends State<VideoDetailPage>
heroTag = Get.arguments['heroTag'];
}
videoDetailController = Get.put(VideoDetailController(), tag: heroTag);
_videoReplyController = Get.put(
VideoReplyController(videoDetailController.oid.value, '0', '1'),
tag: heroTag);
videoIntroController = Get.put(VideoIntroController(), tag: heroTag);
videoIntroController.videoDetail.listen((value) {
if (!context.mounted) return;
@@ -384,6 +390,104 @@ class _VideoDetailPageState extends State<VideoDetailPage>
@override
Widget build(BuildContext context) {
/// tabbar
Widget tabbarBuild = Container(
width: double.infinity,
height: 45,
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
width: 1,
color: Theme.of(context).dividerColor.withOpacity(0.1),
),
),
),
child: Material(
child: Row(
children: [
Flexible(
flex: 1,
child: Obx(
() => TabBar(
padding: EdgeInsets.zero,
controller: videoDetailController.tabCtr,
labelStyle: const TextStyle(fontSize: 13),
labelPadding:
const EdgeInsets.symmetric(horizontal: 10.0), // 设置每个标签的宽度
dividerColor: Colors.transparent,
onTap: (value) {
if (!videoDetailController.tabCtr.indexIsChanging) {
if (value == 0) {
_introController.animToTop();
} else {
_videoReplyController.animToTop();
}
}
},
tabs: [
const Tab(text: '简介'),
Tab(
text:
'评论${_videoReplyController.count.value == -1 ? '' : ' ${_videoReplyController.count.value}'}',
),
],
),
),
),
Flexible(
flex: 1,
child: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
SizedBox(
height: 32,
child: TextButton(
style: ButtonStyle(
padding: WidgetStateProperty.all(EdgeInsets.zero),
),
onPressed: null,
// onPressed: () => videoDetailController.showShootDanmakuSheet(),
child:
const Text('发弹幕', style: TextStyle(fontSize: 12)),
),
),
// SizedBox(
// width: 38,
// height: 38,
// child: Obx(
// () => IconButton(
// onPressed: () {
// plPlayerController?.isOpenDanmu.value =
// !(plPlayerController?.isOpenDanmu.value ??
// false);
// },
// icon: !(plPlayerController?.isOpenDanmu.value ??
// false)
// ? SvgPicture.asset(
// 'assets/images/video/danmu_close.svg',
// // ignore: deprecated_member_use
// color:
// Theme.of(context).colorScheme.outline,
// )
// : SvgPicture.asset(
// 'assets/images/video/danmu_open.svg',
// // ignore: deprecated_member_use
// color:
// Theme.of(context).colorScheme.primary,
// ),
// ),
// ),
// ),
const SizedBox(width: 14),
],
),
)),
],
),
),
);
Widget plPlayer = FutureBuilder(
future: _futureBuilderFuture,
builder: (BuildContext context, AsyncSnapshot snapshot) {
@@ -587,33 +691,17 @@ class _VideoDetailPageState extends State<VideoDetailPage>
Expanded(
child: ColoredBox(
key: Key(heroTag),
color: Theme.of(context).colorScheme.background,
color: Theme.of(context).colorScheme.surface,
child: Column(
children: [
// Opacity(
// opacity: 0,
// child: SizedBox(
// width: context.width,
// height: 0,
// 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(),
// ),
// ),
// ),
// ),
tabbarBuild,
Expanded(
child: TabBarView(
physics: const BouncingScrollPhysics(),
controller: videoDetailController.tabCtr,
children: <Widget>[
CustomScrollView(
controller: _introController,
key: const PageStorageKey<String>('简介'),
slivers: <Widget>[
if (videoDetailController.videoType ==