opt: safearea

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
bggRGjQaUbCoE
2025-04-21 11:15:21 +08:00
parent 95caf111ae
commit 9ad57dccb0
37 changed files with 1660 additions and 1518 deletions

View File

@@ -43,10 +43,10 @@ class DynamicSliverAppBar extends StatefulWidget {
this.forceMaterialTransparency = false, this.forceMaterialTransparency = false,
this.clipBehavior, this.clipBehavior,
this.appBarClipper, this.appBarClipper,
this.hasTabBar = false, this.callback,
}); });
final bool hasTabBar; final ValueChanged<double>? callback;
final Widget? flexibleSpace; final Widget? flexibleSpace;
final Widget? leading; final Widget? leading;
final bool automaticallyImplyLeading; final bool automaticallyImplyLeading;
@@ -113,6 +113,7 @@ class _DynamicSliverAppBarState extends State<DynamicSliverAppBar> {
_height = (_childKey.currentContext!.findRenderObject()! as RenderBox) _height = (_childKey.currentContext!.findRenderObject()! as RenderBox)
.size .size
.height; .height;
widget.callback?.call(_height);
}); });
}); });
} }
@@ -166,7 +167,7 @@ class _DynamicSliverAppBarState extends State<DynamicSliverAppBar> {
onStretchTrigger: widget.onStretchTrigger, onStretchTrigger: widget.onStretchTrigger,
shape: widget.shape, shape: widget.shape,
toolbarHeight: widget.toolbarHeight, toolbarHeight: widget.toolbarHeight,
expandedHeight: _height + (widget.hasTabBar ? 48 : 0), expandedHeight: _height,
leadingWidth: widget.leadingWidth, leadingWidth: widget.leadingWidth,
toolbarTextStyle: widget.toolbarTextStyle, toolbarTextStyle: widget.toolbarTextStyle,
titleTextStyle: widget.titleTextStyle, titleTextStyle: widget.titleTextStyle,

View File

@@ -51,7 +51,9 @@ class _PgcIndexPageState extends State<PgcIndexPage>
int count = (data.order?.isNotEmpty == true ? 1 : 0) + int count = (data.order?.isNotEmpty == true ? 1 : 0) +
(data.filter?.length ?? 0); (data.filter?.length ?? 0);
if (count == 0) return const SizedBox.shrink(); if (count == 0) return const SizedBox.shrink();
return CustomScrollView( return SafeArea(
bottom: false,
child: CustomScrollView(
slivers: [ slivers: [
if (widget.indexType != null) if (widget.indexType != null)
SliverToBoxAdapter(child: const SizedBox(height: 12)), SliverToBoxAdapter(child: const SizedBox(height: 12)),
@@ -75,6 +77,7 @@ class _PgcIndexPageState extends State<PgcIndexPage>
sliver: Obx(() => _buildList(_ctr.loadingState.value)), sliver: Obx(() => _buildList(_ctr.loadingState.value)),
), ),
], ],
),
); );
}), }),
Error() => scrollErrorWidget( Error() => scrollErrorWidget(

View File

@@ -248,10 +248,14 @@ class _BangumiPageState extends CommonPageState<BangumiPage, BangumiController>
length: types.length, length: types.length,
child: Column( child: Column(
children: [ children: [
TabBar( SafeArea(
top: false,
bottom: false,
child: TabBar(
tabs: titles tabs: titles
.map((title) => Tab(text: title)) .map((title) => Tab(text: title))
.toList()), .toList()),
),
Expanded( Expanded(
child: tabBarView( child: tabBarView(
children: types children: types

View File

@@ -48,13 +48,17 @@ abstract class CommonSearchPageState<S extends CommonSearchPage, R, T>
onSubmitted: (value) => controller.onRefresh(), onSubmitted: (value) => controller.onRefresh(),
), ),
), ),
body: CustomScrollView( body: SafeArea(
top: false,
bottom: false,
child: CustomScrollView(
physics: const AlwaysScrollableScrollPhysics(), physics: const AlwaysScrollableScrollPhysics(),
controller: controller.scrollController, controller: controller.scrollController,
slivers: [ slivers: [
Obx(() => _buildBody(controller.loadingState.value)), Obx(() => _buildBody(controller.loadingState.value)),
], ],
), ),
),
); );
} }

View File

@@ -103,10 +103,6 @@ class _DynamicDetailPageState extends State<DynamicDetailPage>
super.initState(); super.initState();
// floor 1原创 2转发 // floor 1原创 2转发
init(); init();
// if (action == 'comment') {
// _visibleTitle = true;
// _titleStreamC.add(true);
// }
_fabAnimationCtr = AnimationController( _fabAnimationCtr = AnimationController(
vsync: this, vsync: this,
@@ -340,7 +336,10 @@ class _DynamicDetailPageState extends State<DynamicDetailPage>
] ]
: null, : null,
), ),
body: context.orientation == Orientation.portrait body: SafeArea(
top: false,
bottom: false,
child: context.orientation == Orientation.portrait
? refreshIndicator( ? refreshIndicator(
onRefresh: () async { onRefresh: () async {
await _dynamicDetailController.onRefresh(); await _dynamicDetailController.onRefresh();
@@ -348,6 +347,7 @@ class _DynamicDetailPageState extends State<DynamicDetailPage>
child: _buildBody(context.orientation), child: _buildBody(context.orientation),
) )
: _buildBody(context.orientation), : _buildBody(context.orientation),
),
); );
} }

View File

@@ -37,7 +37,9 @@ class _FansPageState extends State<FansPage> {
_fansController.isOwner.value ? '我的粉丝' : '${_fansController.name}的粉丝', _fansController.isOwner.value ? '我的粉丝' : '${_fansController.name}的粉丝',
), ),
), ),
body: refreshIndicator( body: SafeArea(
bottom: false,
child: refreshIndicator(
onRefresh: () async => await _fansController.onRefresh(), onRefresh: () async => await _fansController.onRefresh(),
child: CustomScrollView( child: CustomScrollView(
physics: const AlwaysScrollableScrollPhysics(), physics: const AlwaysScrollableScrollPhysics(),
@@ -47,6 +49,7 @@ class _FansPageState extends State<FansPage> {
], ],
), ),
), ),
),
); );
} }

View File

@@ -87,7 +87,11 @@ class _FavFolderSortPageState extends State<FavFolderSortPage> {
const SizedBox(width: 16), const SizedBox(width: 16),
], ],
), ),
body: _buildBody, body: SafeArea(
top: false,
bottom: false,
child: _buildBody,
),
); );
} }

View File

@@ -136,7 +136,13 @@ class _FavPageState extends State<FavPage> with SingleTickerProviderStateMixin {
), ),
body: tabBarView( body: tabBarView(
controller: _tabController, controller: _tabController,
children: _FavType.values.map((item) => item.page).toList(), children: _FavType.values
.map((item) => SafeArea(
top: false,
bottom: false,
child: item.page,
))
.toList(),
), ),
); );
} }

View File

@@ -93,7 +93,11 @@ class _FavSortPageState extends State<FavSortPage> {
const SizedBox(width: 16), const SizedBox(width: 16),
], ],
), ),
body: _buildBody, body: SafeArea(
top: false,
bottom: false,
child: _buildBody,
),
); );
} }

View File

@@ -75,7 +75,10 @@ class _FavDetailPageState extends State<FavDetailPage> {
) )
: const SizedBox.shrink(), : const SizedBox.shrink(),
), ),
body: refreshIndicator( body: SafeArea(
top: false,
bottom: false,
child: refreshIndicator(
onRefresh: () async { onRefresh: () async {
await _favDetailController.onRefresh(); await _favDetailController.onRefresh();
}, },
@@ -91,7 +94,7 @@ class _FavDetailPageState extends State<FavDetailPage> {
icon: const Icon(Icons.close_outlined), icon: const Icon(Icons.close_outlined),
) )
: null, : null,
expandedHeight: 220 - MediaQuery.of(context).padding.top, expandedHeight: 200 - MediaQuery.of(context).padding.top,
pinned: true, pinned: true,
title: _favDetailController.enableMultiSelect.value title: _favDetailController.enableMultiSelect.value
? Text( ? Text(
@@ -202,9 +205,10 @@ class _FavDetailPageState extends State<FavDetailPage> {
arguments: { arguments: {
'type': 0, 'type': 0,
'mediaId': int.parse(mediaId), 'mediaId': int.parse(mediaId),
'title': _favDetailController.item.value.title, 'title':
'count': _favDetailController.item.value.title,
_favDetailController.item.value.mediaCount, 'count': _favDetailController
.item.value.mediaCount,
'isOwner': _favDetailController.isOwner.value, 'isOwner': _favDetailController.isOwner.value,
}, },
), ),
@@ -222,8 +226,8 @@ class _FavDetailPageState extends State<FavDetailPage> {
parameters: {'mediaId': mediaId}, parameters: {'mediaId': mediaId},
)?.then((res) { )?.then((res) {
if (res is FavFolderItemData) { if (res is FavFolderItemData) {
_favDetailController.item.value = _favDetailController
res; .item.value = res;
} }
}); });
}, },
@@ -238,7 +242,8 @@ class _FavDetailPageState extends State<FavDetailPage> {
Future.delayed( Future.delayed(
const Duration( const Duration(
milliseconds: 200), () { milliseconds: 200), () {
_favDetailController.onReload(); _favDetailController
.onReload();
}); });
} else { } else {
SmartDialog.showToast( SmartDialog.showToast(
@@ -250,16 +255,18 @@ class _FavDetailPageState extends State<FavDetailPage> {
), ),
PopupMenuItem( PopupMenuItem(
onTap: () { onTap: () {
if (_favDetailController.loadingState if (_favDetailController
.loadingState
.value is Success && .value is Success &&
((_favDetailController ((_favDetailController
.loadingState .loadingState
.value as Success) .value
as Success)
.response as List?) .response as List?)
?.isNotEmpty == ?.isNotEmpty ==
true) { true) {
if ((_favDetailController.item.value if ((_favDetailController.item
.mediaCount ?? .value.mediaCount ??
0) > 0) >
1000) { 1000) {
SmartDialog.showToast( SmartDialog.showToast(
@@ -344,13 +351,15 @@ class _FavDetailPageState extends State<FavDetailPage> {
height: 110, height: 110,
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment:
MainAxisAlignment.start,
crossAxisAlignment: crossAxisAlignment:
CrossAxisAlignment.start, CrossAxisAlignment.start,
children: [ children: [
const SizedBox(height: 4), const SizedBox(height: 4),
Text( Text(
_favDetailController.item.value.title ?? _favDetailController
.item.value.title ??
'', '',
style: TextStyle( style: TextStyle(
fontSize: Theme.of(context) fontSize: Theme.of(context)
@@ -415,12 +424,14 @@ class _FavDetailPageState extends State<FavDetailPage> {
), ),
), ),
), ),
Obx(() => _buildBody(_favDetailController.loadingState.value)), Obx(() =>
_buildBody(_favDetailController.loadingState.value)),
], ],
), ),
), ),
), ),
), ),
),
); );
} }

View File

@@ -76,7 +76,10 @@ class _FollowPageState extends State<FollowPage> {
if (data['status']) { if (data['status']) {
return Column( return Column(
children: [ children: [
TabBar( SafeArea(
top: false,
bottom: false,
child: TabBar(
controller: _followController.tabController, controller: _followController.tabController,
isScrollable: true, isScrollable: true,
tabAlignment: TabAlignment.start, tabAlignment: TabAlignment.start,
@@ -86,6 +89,7 @@ class _FollowPageState extends State<FollowPage> {
] ]
], ],
), ),
),
Expanded( Expanded(
child: Material( child: Material(
color: Colors.transparent, color: Colors.transparent,

View File

@@ -92,12 +92,12 @@ class _FollowListState extends State<FollowList> {
} }
}, },
) )
: errorWidget( : scrollErrorWidget(
callback: () => widget.ctr.queryFollowings('init'), callback: () => widget.ctr.queryFollowings('init'),
), ),
); );
} else { } else {
return errorWidget( return scrollErrorWidget(
errMsg: data['msg'], errMsg: data['msg'],
callback: () => widget.ctr.queryFollowings('init'), callback: () => widget.ctr.queryFollowings('init'),
); );

View File

@@ -107,12 +107,12 @@ class _OwnerFollowListState extends State<OwnerFollowList>
); );
}, },
) )
: errorWidget( : scrollErrorWidget(
callback: () => widget.ctr.queryFollowings('init'), callback: () => widget.ctr.queryFollowings('init'),
), ),
); );
} else { } else {
return errorWidget( return scrollErrorWidget(
errMsg: data['msg'], errMsg: data['msg'],
callback: () => widget.ctr.queryFollowings('init'), callback: () => widget.ctr.queryFollowings('init'),
); );

View File

@@ -182,7 +182,10 @@ class _HistoryPageState extends State<HistoryPage>
? Column( ? Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
TabBar( SafeArea(
top: false,
bottom: false,
child: TabBar(
controller: _historyController.tabController, controller: _historyController.tabController,
onTap: (index) { onTap: (index) {
if (_historyController if (_historyController
@@ -203,6 +206,7 @@ class _HistoryPageState extends State<HistoryPage>
), ),
], ],
), ),
),
Expanded( Expanded(
child: Material( child: Material(
color: Colors.transparent, color: Colors.transparent,
@@ -229,7 +233,10 @@ class _HistoryPageState extends State<HistoryPage>
); );
} }
Widget get _buildPage => refreshIndicator( Widget get _buildPage => SafeArea(
top: false,
bottom: false,
child: refreshIndicator(
onRefresh: () async { onRefresh: () async {
await _historyController.onRefresh(); await _historyController.onRefresh();
}, },
@@ -240,6 +247,7 @@ class _HistoryPageState extends State<HistoryPage>
Obx(() => _buildBody(_historyController.loadingState.value)), Obx(() => _buildBody(_historyController.loadingState.value)),
], ],
), ),
),
); );
Widget _buildBody(LoadingState<List<HisListItem>?> loadingState) { Widget _buildBody(LoadingState<List<HisListItem>?> loadingState) {

View File

@@ -337,11 +337,15 @@ class _HtmlRenderPageState extends State<HtmlRenderPage>
const SizedBox(width: 6) const SizedBox(width: 6)
], ],
), ),
body: Stack( body: SafeArea(
top: false,
bottom: false,
child: Stack(
children: [ children: [
OrientationBuilder( OrientationBuilder(
builder: (context, orientation) { builder: (context, orientation) {
double padding = max(context.width / 2 - Grid.smallCardWidth, 0); double padding =
max(context.width / 2 - Grid.smallCardWidth, 0);
return Row( return Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@@ -369,13 +373,15 @@ class _HtmlRenderPageState extends State<HtmlRenderPage>
: EdgeInsets.only( : EdgeInsets.only(
left: padding / 4, left: padding / 4,
bottom: bottom:
MediaQuery.paddingOf(context).bottom + 80, MediaQuery.paddingOf(context).bottom +
80,
), ),
sliver: _buildContent, sliver: _buildContent,
), ),
if (orientation == Orientation.portrait) ...[ if (orientation == Orientation.portrait) ...[
SliverPadding( SliverPadding(
padding: EdgeInsets.symmetric(horizontal: padding), padding:
EdgeInsets.symmetric(horizontal: padding),
sliver: SliverToBoxAdapter( sliver: SliverToBoxAdapter(
child: Divider( child: Divider(
thickness: 8, thickness: 8,
@@ -386,14 +392,16 @@ class _HtmlRenderPageState extends State<HtmlRenderPage>
), ),
), ),
SliverPadding( SliverPadding(
padding: EdgeInsets.symmetric(horizontal: padding), padding:
EdgeInsets.symmetric(horizontal: padding),
sliver: SliverToBoxAdapter(child: replyHeader()), sliver: SliverToBoxAdapter(child: replyHeader()),
), ),
SliverPadding( SliverPadding(
padding: EdgeInsets.symmetric(horizontal: padding), padding:
EdgeInsets.symmetric(horizontal: padding),
sliver: Obx( sliver: Obx(
() => () => replyList(
replyList(_htmlRenderCtr.loadingState.value), _htmlRenderCtr.loadingState.value),
), ),
), ),
], ],
@@ -513,7 +521,8 @@ class _HtmlRenderPageState extends State<HtmlRenderPage>
), ),
), ),
padding: EdgeInsets.only( padding: EdgeInsets.only(
bottom: MediaQuery.paddingOf(context) bottom:
MediaQuery.paddingOf(context)
.bottom), .bottom),
child: Row( child: Row(
mainAxisAlignment: mainAxisAlignment:
@@ -572,9 +581,8 @@ class _HtmlRenderPageState extends State<HtmlRenderPage>
semanticLabel: "转发", semanticLabel: "转发",
), ),
style: TextButton.styleFrom( style: TextButton.styleFrom(
padding: padding: const EdgeInsets
const EdgeInsets.fromLTRB( .fromLTRB(15, 0, 15, 0),
15, 0, 15, 0),
foregroundColor: foregroundColor:
Theme.of(context) Theme.of(context)
.colorScheme .colorScheme
@@ -632,8 +640,8 @@ class _HtmlRenderPageState extends State<HtmlRenderPage>
child: Builder( child: Builder(
builder: (context) => builder: (context) =>
TextButton.icon( TextButton.icon(
onPressed: () => onPressed: () => RequestUtils
RequestUtils.onLikeDynamic( .onLikeDynamic(
_htmlRenderCtr.item.value, _htmlRenderCtr.item.value,
() { () {
if (context.mounted) { if (context.mounted) {
@@ -670,7 +678,8 @@ class _HtmlRenderPageState extends State<HtmlRenderPage>
: Theme.of(context) : Theme.of(context)
.colorScheme .colorScheme
.outline, .outline,
semanticLabel: _htmlRenderCtr semanticLabel:
_htmlRenderCtr
.item .item
.value .value
.modules .modules
@@ -682,9 +691,8 @@ class _HtmlRenderPageState extends State<HtmlRenderPage>
: "点赞", : "点赞",
), ),
style: TextButton.styleFrom( style: TextButton.styleFrom(
padding: padding: const EdgeInsets
const EdgeInsets.fromLTRB( .fromLTRB(15, 0, 15, 0),
15, 0, 15, 0),
foregroundColor: foregroundColor:
Theme.of(context) Theme.of(context)
.colorScheme .colorScheme
@@ -753,6 +761,7 @@ class _HtmlRenderPageState extends State<HtmlRenderPage>
), ),
], ],
), ),
),
); );
} }

View File

@@ -88,7 +88,10 @@ class _LaterPageState extends State<LaterPage>
), ),
body: Column( body: Column(
children: [ children: [
TabBar( SafeArea(
top: false,
bottom: false,
child: TabBar(
isScrollable: true, isScrollable: true,
controller: _tabController, controller: _tabController,
tabAlignment: TabAlignment.start, tabAlignment: TabAlignment.start,
@@ -107,14 +110,20 @@ class _LaterPageState extends State<LaterPage>
} }
}, },
), ),
),
Expanded( Expanded(
child: TabBarView( child: TabBarView(
physics: _baseCtr.enableMultiSelect.value physics: _baseCtr.enableMultiSelect.value
? const NeverScrollableScrollPhysics() ? const NeverScrollableScrollPhysics()
: const CustomTabBarViewScrollPhysics(), : const CustomTabBarViewScrollPhysics(),
controller: _tabController, controller: _tabController,
children: children: LaterViewType.values
LaterViewType.values.map((item) => item.page).toList(), .map((item) => SafeArea(
top: false,
bottom: false,
child: item.page,
))
.toList(),
), ),
), ),
], ],

View File

@@ -6,6 +6,7 @@ import 'package:PiliPlus/pages/live_room/send_dm_panel.dart';
import 'package:PiliPlus/pages/live_room/widgets/chat.dart'; import 'package:PiliPlus/pages/live_room/widgets/chat.dart';
import 'package:PiliPlus/pages/live_room/widgets/header_control.dart'; import 'package:PiliPlus/pages/live_room/widgets/header_control.dart';
import 'package:PiliPlus/services/service_locator.dart'; import 'package:PiliPlus/services/service_locator.dart';
import 'package:PiliPlus/utils/extension.dart';
import 'package:PiliPlus/utils/page_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart';
import 'package:PiliPlus/utils/utils.dart'; import 'package:PiliPlus/utils/utils.dart';
import 'package:cached_network_image/cached_network_image.dart'; import 'package:cached_network_image/cached_network_image.dart';
@@ -203,7 +204,7 @@ class _LiveRoomPageState extends State<LiveRoomPage>
), ),
); );
} else { } else {
return const SizedBox(); return const SizedBox.shrink();
} }
}, },
), ),
@@ -228,9 +229,8 @@ class _LiveRoomPageState extends State<LiveRoomPage>
fit: BoxFit.cover, fit: BoxFit.cover,
width: Get.width, width: Get.width,
height: Get.height, height: Get.height,
imageUrl: Utils.thumbnailImgUrl( imageUrl: _liveRoomController.roomInfoH5.value
_liveRoomController.roomInfoH5.value.roomInfo! .roomInfo!.appBackground!.http2https,
.appBackground!),
) )
: Image.asset( : Image.asset(
'assets/images/live/default_bg.webp', 'assets/images/live/default_bg.webp',
@@ -239,7 +239,12 @@ class _LiveRoomPageState extends State<LiveRoomPage>
), ),
), ),
), ),
isPortrait SafeArea(
top: false,
left: !isFullScreen,
right: !isFullScreen,
bottom: false,
child: isPortrait
? Obx( ? Obx(
() { () {
if (_liveRoomController.isPortrait.value) { if (_liveRoomController.isPortrait.value) {
@@ -258,6 +263,7 @@ class _LiveRoomPageState extends State<LiveRoomPage>
_buildBodyH, _buildBodyH,
], ],
), ),
),
], ],
), ),
); );
@@ -458,10 +464,13 @@ class _LiveRoomPageState extends State<LiveRoomPage>
children: [ children: [
Obx( Obx(
() => Container( () => Container(
margin:
EdgeInsets.only(bottom: MediaQuery.paddingOf(context).bottom),
color: isFullScreen ? Colors.black : null, color: isFullScreen ? Colors.black : null,
width: isFullScreen ? Get.size.width : videoWidth, width: isFullScreen ? Get.size.width : videoWidth,
height: isFullScreen ? Get.size.height : Get.size.width * 9 / 16, height: isFullScreen ? Get.size.height : Get.size.width * 9 / 16,
child: MediaQuery.removePadding( child: MediaQuery.removePadding(
removeTop: true,
removeRight: true, removeRight: true,
context: context, context: context,
child: videoPlayerPanel(fill: Colors.transparent), child: videoPlayerPanel(fill: Colors.transparent),
@@ -469,15 +478,11 @@ class _LiveRoomPageState extends State<LiveRoomPage>
), ),
), ),
Expanded( Expanded(
child: SafeArea(
left: false,
top: false,
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: _buildBottomWidget, children: _buildBottomWidget,
), ),
), ),
),
], ],
), ),
); );

View File

@@ -173,6 +173,7 @@ class _MainAppState extends State<MainApp>
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final bool isPortrait = context.orientation == Orientation.portrait;
return PopScope( return PopScope(
canPop: false, canPop: false,
onPopInvokedWithResult: (bool didPop, Object? result) async { onPopInvokedWithResult: (bool didPop, Object? result) async {
@@ -200,8 +201,7 @@ class _MainAppState extends State<MainApp>
body: Row( body: Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
if (useSideBar || if (useSideBar || !isPortrait) ...[
context.orientation == Orientation.landscape) ...[
Obx( Obx(
() => _mainController.navigationBars.length > 1 () => _mainController.navigationBars.length > 1
? context.isTablet ? context.isTablet
@@ -298,12 +298,14 @@ class _MainAppState extends State<MainApp>
), ),
], ],
Expanded( Expanded(
child: SafeArea(
top: false,
bottom: false,
left: isPortrait,
child: _mainController.mainTabBarView child: _mainController.mainTabBarView
? CustomTabBarView( ? CustomTabBarView(
scrollDirection: scrollDirection:
context.orientation == Orientation.portrait isPortrait ? Axis.horizontal : Axis.vertical,
? Axis.horizontal
: Axis.vertical,
physics: const NeverScrollableScrollPhysics(), physics: const NeverScrollableScrollPhysics(),
controller: _mainController.controller, controller: _mainController.controller,
children: _mainController.pages, children: _mainController.pages,
@@ -314,10 +316,10 @@ class _MainAppState extends State<MainApp>
children: _mainController.pages, children: _mainController.pages,
), ),
), ),
),
], ],
), ),
bottomNavigationBar: useSideBar || bottomNavigationBar: useSideBar || !isPortrait
context.orientation == Orientation.landscape
? null ? null
: StreamBuilder( : StreamBuilder(
stream: _mainController.hideTabBar stream: _mainController.hideTabBar

View File

@@ -40,7 +40,10 @@ class _MediaPageState extends CommonPageState<MediaPage, MediaController>
Widget build(BuildContext context) { Widget build(BuildContext context) {
super.build(context); super.build(context);
Color primary = Theme.of(context).colorScheme.primary; Color primary = Theme.of(context).colorScheme.primary;
return Scaffold( return MediaQuery.removePadding(
context: context,
removeLeft: context.orientation == Orientation.landscape,
child: Scaffold(
backgroundColor: Colors.transparent, backgroundColor: Colors.transparent,
appBar: AppBar( appBar: AppBar(
toolbarHeight: 30, toolbarHeight: 30,
@@ -98,6 +101,7 @@ class _MediaPageState extends CommonPageState<MediaPage, MediaController>
) )
], ],
), ),
),
); );
} }

View File

@@ -33,7 +33,6 @@ class MemberControllerNew extends CommonDataController<Data, dynamic>
late List<Tab> tabs; late List<Tab> tabs;
List<Tab2>? tab2; List<Tab2>? tab2;
RxInt contributeInitialIndex = 0.obs; RxInt contributeInitialIndex = 0.obs;
double top = 0;
bool? hasSeasonOrSeries; bool? hasSeasonOrSeries;
final fromViewAid = Get.parameters['from_view_aid']; final fromViewAid = Get.parameters['from_view_aid'];

View File

@@ -31,6 +31,7 @@ class _MemberPageNewState extends State<MemberPageNew> {
late final String _heroTag; late final String _heroTag;
late final MemberControllerNew _userController; late final MemberControllerNew _userController;
final _key = GlobalKey<ExtendedNestedScrollViewState>(); final _key = GlobalKey<ExtendedNestedScrollViewState>();
int _offset = 120;
@override @override
void initState() { void initState() {
@@ -45,8 +46,10 @@ class _MemberPageNewState extends State<MemberPageNew> {
} }
void listener() { void listener() {
if (_userController.scrollController.hasClients) {
_userController.showUname.value = _userController.showUname.value =
_userController.scrollController.offset >= 120; _userController.scrollController.offset >= _offset;
}
} }
@override @override
@@ -57,138 +60,28 @@ class _MemberPageNewState extends State<MemberPageNew> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
if (_userController.top == 0) {
_userController.top = MediaQuery.of(context).padding.top;
}
return Scaffold( return Scaffold(
extendBody: true,
extendBodyBehindAppBar: true,
resizeToAvoidBottomInset: false, resizeToAvoidBottomInset: false,
body: Obx( appBar: AppBar(
() => _userController.loadingState.value is Success forceMaterialTransparency: true,
? LayoutBuilder(
builder: (context, constraints) {
return ExtendedNestedScrollView(
key: _key,
controller: _userController.scrollController,
onlyOneScrollInBody: true,
headerSliverBuilder: (context, innerBoxIsScrolled) {
return [
SliverOverlapAbsorber(
handle: ExtendedNestedScrollView
.sliverOverlapAbsorberHandleFor(context),
sliver: _buildAppBar(
isV: constraints.maxHeight > constraints.maxWidth,
),
),
];
},
body: _userController.tab2?.isNotEmpty == true
? LayoutBuilder(
builder: (context, _) {
return Padding(
padding: EdgeInsets.only(
top: ExtendedNestedScrollView
.sliverOverlapAbsorberHandleFor(
context)
.layoutExtent ??
0,
),
child: _buildBody,
);
},
)
: Center(child: const Text('EMPTY')),
);
},
)
: Center(
child: _buildUserInfo(_userController.loadingState.value),
),
),
);
}
Widget get _buildTab => Material(
color: Theme.of(context).colorScheme.surface,
child: TabBar(
controller: _userController.tabController,
tabs: _userController.tabs,
onTap: (value) {
if (_userController.tabController?.indexIsChanging == false) {
_key.currentState?.outerController.animToTop();
}
},
),
);
Widget get _buildBody => SafeArea(
top: false,
bottom: false,
child: tabBarView(
controller: _userController.tabController,
children: _userController.tab2!.map((item) {
return switch (item.param!) {
'home' => MemberHome(heroTag: _heroTag),
'dynamic' => MemberDynamicsPage(mid: _mid),
'contribute' => Obx(
() => MemberContribute(
heroTag: _heroTag,
initialIndex: _userController.contributeInitialIndex.value,
mid: _mid,
),
),
'bangumi' => MemberBangumi(
heroTag: _heroTag,
mid: _mid,
),
'favorite' => MemberFavorite(
heroTag: _heroTag,
mid: _mid,
),
_ => Center(child: Text(item.title ?? '')),
};
}).toList(),
),
);
Widget _buildAppBar({bool needTab = true, bool isV = true}) =>
DynamicSliverAppBar(
primary: false,
leading: Padding(
padding: EdgeInsets.only(top: _userController.top),
child: const BackButton(),
),
hasTabBar: (_userController.tab2?.length ?? 0) > 1,
toolbarHeight: kToolbarHeight + _userController.top,
title: IgnorePointer( title: IgnorePointer(
child: Obx(() => _userController.showUname.value && child: Obx(
() => _userController.showUname.value &&
_userController.username != null _userController.username != null
? Padding( ? Text(_userController.username!)
padding: EdgeInsets.only(top: _userController.top), : const SizedBox.shrink(),
child: Text(_userController.username!), ),
)
: const SizedBox.shrink()),
), ),
pinned: true,
flexibleSpace: _buildUserInfo(_userController.loadingState.value, isV),
bottom: needTab && (_userController.tab2?.length ?? -1) > 1
? PreferredSize(
preferredSize: Size.fromHeight(48),
child: _buildTab,
)
: null,
actions: [ actions: [
Padding( IconButton(
padding: EdgeInsets.only(top: _userController.top),
child: IconButton(
tooltip: '搜索', tooltip: '搜索',
onPressed: () => Get.toNamed( onPressed: () => Get.toNamed(
'/memberSearch?mid=$_mid&uname=${_userController.username}'), '/memberSearch?mid=$_mid&uname=${_userController.username}'),
icon: const Icon(Icons.search_outlined), icon: const Icon(Icons.search_outlined),
), ),
), PopupMenuButton(
Padding(
padding: EdgeInsets.only(top: _userController.top),
child: PopupMenuButton(
icon: const Icon(Icons.more_vert), icon: const Icon(Icons.more_vert),
itemBuilder: (BuildContext context) => <PopupMenuEntry>[ itemBuilder: (BuildContext context) => <PopupMenuEntry>[
if (_userController.ownerMid != _mid) ...[ if (_userController.ownerMid != _mid) ...[
@@ -213,9 +106,7 @@ class _MemberPageNewState extends State<MemberPageNew> {
children: [ children: [
const Icon(Icons.share_outlined, size: 19), const Icon(Icons.share_outlined, size: 19),
const SizedBox(width: 10), const SizedBox(width: 10),
Text(_userController.ownerMid != _mid Text(_userController.ownerMid != _mid ? '分享UP主' : '分享我的主页'),
? '分享UP主'
: '分享我的主页'),
], ],
), ),
), ),
@@ -259,10 +150,107 @@ class _MemberPageNewState extends State<MemberPageNew> {
], ],
], ],
), ),
),
const SizedBox(width: 4), const SizedBox(width: 4),
], ],
),
body: Obx(
() => _userController.loadingState.value is Success
? LayoutBuilder(
builder: (context, constraints) {
return ExtendedNestedScrollView(
key: _key,
controller: _userController.scrollController,
onlyOneScrollInBody: true,
pinnedHeaderSliverHeightBuilder: () {
return kToolbarHeight +
MediaQuery.paddingOf(this.context).top.toInt();
},
headerSliverBuilder: (context, innerBoxIsScrolled) {
return [
_buildAppBar(
isV: constraints.maxHeight > constraints.maxWidth,
),
];
},
body: _userController.tab2?.isNotEmpty == true
? Column(
children: [
if ((_userController.tab2?.length ?? 0) > 1)
_buildTab,
Expanded(child: _buildBody),
],
)
: Center(child: const Text('EMPTY')),
); );
},
)
: Center(
child: _buildUserInfo(_userController.loadingState.value),
),
),
);
}
Widget get _buildTab => Material(
color: Theme.of(context).colorScheme.surface,
child: SafeArea(
top: false,
bottom: false,
child: TabBar(
controller: _userController.tabController,
tabs: _userController.tabs,
onTap: (value) {
if (_userController.tabController?.indexIsChanging == false) {
_key.currentState?.outerController.animToTop();
}
},
),
),
);
Widget get _buildBody => SafeArea(
top: false,
bottom: false,
child: tabBarView(
controller: _userController.tabController,
children: _userController.tab2!.map((item) {
return switch (item.param!) {
'home' => MemberHome(heroTag: _heroTag),
'dynamic' => MemberDynamicsPage(mid: _mid),
'contribute' => Obx(
() => MemberContribute(
heroTag: _heroTag,
initialIndex: _userController.contributeInitialIndex.value,
mid: _mid,
),
),
'bangumi' => MemberBangumi(
heroTag: _heroTag,
mid: _mid,
),
'favorite' => MemberFavorite(
heroTag: _heroTag,
mid: _mid,
),
_ => Center(child: Text(item.title ?? '')),
};
}).toList(),
),
);
Widget _buildAppBar({bool isV = true}) {
return DynamicSliverAppBar(
pinned: true,
primary: false,
automaticallyImplyLeading: false,
toolbarHeight: kToolbarHeight + MediaQuery.paddingOf(context).top,
flexibleSpace: _buildUserInfo(_userController.loadingState.value, isV),
callback: (value) {
_offset = (value - 56 - MediaQuery.paddingOf(context).top).toInt();
listener();
},
);
}
Widget _errorWidget(msg) { Widget _errorWidget(msg) {
return errorWidget( return errorWidget(

View File

@@ -118,6 +118,12 @@ class UserInfoCard extends StatelessWidget {
onTap: () => Utils.copyText(card.name!), onTap: () => Utils.copyText(card.name!),
child: Text( child: Text(
card.name!, card.name!,
strutStyle: StrutStyle(
height: 1,
leading: 0,
fontSize: 17,
fontWeight: FontWeight.bold,
),
style: TextStyle( style: TextStyle(
height: 1, height: 1,
fontSize: 17, fontSize: 17,
@@ -136,8 +142,7 @@ class UserInfoCard extends StatelessWidget {
), ),
if (card.vip?.vipStatus == 1) if (card.vip?.vipStatus == 1)
CachedNetworkImage( CachedNetworkImage(
imageUrl: imageUrl: Utils.thumbnailImgUrl(card.vip!.label!.image!, 80),
Utils.thumbnailImgUrl(card.vip!.label!.image!.http2https),
height: 20, height: 20,
placeholder: (context, url) { placeholder: (context, url) {
return const SizedBox.shrink(); return const SizedBox.shrink();
@@ -612,7 +617,10 @@ class UserInfoCard extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
_buildHeader(context), // _buildHeader(context),
SizedBox(
height: Get.mediaQuery.padding.bottom + 56,
),
SafeArea( SafeArea(
top: false, top: false,
bottom: false, bottom: false,

View File

@@ -39,7 +39,10 @@ class _MemberCoinPageState extends State<MemberCoinPage> {
appBar: AppBar( appBar: AppBar(
title: Text('${widget.mid == _ownerMid ? '' : '${widget.name}'}'), title: Text('${widget.mid == _ownerMid ? '' : '${widget.name}'}'),
), ),
body: CustomScrollView( body: SafeArea(
top: false,
bottom: false,
child: CustomScrollView(
slivers: [ slivers: [
SliverPadding( SliverPadding(
padding: EdgeInsets.only( padding: EdgeInsets.only(
@@ -52,6 +55,7 @@ class _MemberCoinPageState extends State<MemberCoinPage> {
), ),
], ],
), ),
),
); );
} }

View File

@@ -39,7 +39,10 @@ class _MemberLikePageState extends State<MemberLikePage> {
appBar: AppBar( appBar: AppBar(
title: Text('${widget.mid == _ownerMid ? '' : '${widget.name}'}'), title: Text('${widget.mid == _ownerMid ? '' : '${widget.name}'}'),
), ),
body: CustomScrollView( body: SafeArea(
top: false,
bottom: false,
child: CustomScrollView(
slivers: [ slivers: [
SliverPadding( SliverPadding(
padding: EdgeInsets.only( padding: EdgeInsets.only(
@@ -52,6 +55,7 @@ class _MemberLikePageState extends State<MemberLikePage> {
), ),
], ],
), ),
),
); );
} }

View File

@@ -28,7 +28,10 @@ class _SearchArchiveState extends State<SearchArchive>
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
super.build(context); super.build(context);
return refreshIndicator( return SafeArea(
top: false,
bottom: false,
child: refreshIndicator(
onRefresh: () async { onRefresh: () async {
await widget.ctr.refreshArchive(); await widget.ctr.refreshArchive();
}, },
@@ -45,6 +48,7 @@ class _SearchArchiveState extends State<SearchArchive>
) )
], ],
), ),
),
); );
} }

View File

@@ -30,7 +30,10 @@ class _SearchDynamicState extends State<SearchDynamic>
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
super.build(context); super.build(context);
return refreshIndicator( return SafeArea(
top: false,
bottom: false,
child: refreshIndicator(
onRefresh: () async { onRefresh: () async {
await widget.ctr.refreshDynamic(); await widget.ctr.refreshDynamic();
}, },
@@ -46,6 +49,7 @@ class _SearchDynamicState extends State<SearchDynamic>
) )
], ],
), ),
),
); );
} }

View File

@@ -55,7 +55,10 @@ class _MemberSearchPageState extends State<MemberSearchPage> {
() => _memberSearchCtr.hasData.value () => _memberSearchCtr.hasData.value
? Column( ? Column(
children: [ children: [
TabBar( SafeArea(
top: false,
bottom: false,
child: TabBar(
controller: _memberSearchCtr.tabController, controller: _memberSearchCtr.tabController,
tabs: [ tabs: [
Obx( Obx(
@@ -72,6 +75,7 @@ class _MemberSearchPageState extends State<MemberSearchPage> {
), ),
], ],
), ),
),
Expanded( Expanded(
child: tabBarView( child: tabBarView(
controller: _memberSearchCtr.tabController, controller: _memberSearchCtr.tabController,

View File

@@ -52,7 +52,9 @@ class _ColorSelectPageState extends State<ColorSelectPage> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar(title: const Text('选择应用主题')), appBar: AppBar(title: const Text('选择应用主题')),
body: ListView( body: SafeArea(
bottom: false,
child: ListView(
children: [ children: [
ListTile( ListTile(
onTap: () async { onTap: () async {
@@ -82,7 +84,8 @@ class _ColorSelectPageState extends State<ColorSelectPage> {
child: const Icon(Icons.flashlight_on_outlined), child: const Icon(Icons.flashlight_on_outlined),
), ),
title: Text('主题模式', style: titleStyle), title: Text('主题模式', style: titleStyle),
subtitle: Obx(() => Text('当前模式:${ctr.themeType.value.description}', subtitle: Obx(() => Text(
'当前模式:${ctr.themeType.value.description}',
style: subTitleStyle)), style: subTitleStyle)),
), ),
Obx( Obx(
@@ -182,7 +185,8 @@ class _ColorSelectPageState extends State<ColorSelectPage> {
() => SizedBox( () => SizedBox(
height: ctr.type.value == 0 ? 0 : null, height: ctr.type.value == 0 ? 0 : null,
child: Padding( child: Padding(
padding: const EdgeInsets.only(top: 12, left: 12, right: 12), padding:
const EdgeInsets.only(top: 12, left: 12, right: 12),
child: Wrap( child: Wrap(
alignment: WrapAlignment.center, alignment: WrapAlignment.center,
spacing: 22, spacing: 22,
@@ -194,7 +198,8 @@ class _ColorSelectPageState extends State<ColorSelectPage> {
return GestureDetector( return GestureDetector(
onTap: () { onTap: () {
ctr.currentColor.value = index; ctr.currentColor.value = index;
ctr.setting.put(SettingBoxKey.customColor, index); ctr.setting
.put(SettingBoxKey.customColor, index);
Get.forceAppUpdate(); Get.forceAppUpdate();
}, },
child: Column( child: Column(
@@ -213,9 +218,11 @@ class _ColorSelectPageState extends State<ColorSelectPage> {
), ),
), ),
child: AnimatedOpacity( child: AnimatedOpacity(
opacity: opacity: ctr.currentColor.value == index
ctr.currentColor.value == index ? 1 : 0, ? 1
duration: const Duration(milliseconds: 200), : 0,
duration:
const Duration(milliseconds: 200),
child: const Icon( child: const Icon(
Icons.done, Icons.done,
color: Colors.black, color: Colors.black,
@@ -229,7 +236,9 @@ class _ColorSelectPageState extends State<ColorSelectPage> {
style: TextStyle( style: TextStyle(
fontSize: 12, fontSize: 12,
color: ctr.currentColor.value != index color: ctr.currentColor.value != index
? Theme.of(context).colorScheme.outline ? Theme.of(context)
.colorScheme
.outline
: null, : null,
), ),
), ),
@@ -267,6 +276,7 @@ class _ColorSelectPageState extends State<ColorSelectPage> {
], ],
], ],
), ),
),
); );
} }
} }

View File

@@ -48,7 +48,8 @@ class _FontSizeSelectPageState extends State<FontSizeSelectPage> {
const SizedBox(width: 12) const SizedBox(width: 12)
], ],
), ),
body: Column( body: SafeArea(
child: Column(
children: [ children: [
Expanded( Expanded(
child: Center( child: Center(
@@ -60,12 +61,7 @@ class _FontSizeSelectPageState extends State<FontSizeSelectPage> {
), ),
Container( Container(
width: double.infinity, width: double.infinity,
padding: EdgeInsets.only( padding: EdgeInsets.all(20),
left: 20,
right: 20,
top: 20,
bottom: MediaQuery.of(context).padding.bottom + 20,
),
decoration: BoxDecoration( decoration: BoxDecoration(
border: Border( border: Border(
top: BorderSide( top: BorderSide(
@@ -101,6 +97,7 @@ class _FontSizeSelectPageState extends State<FontSizeSelectPage> {
) )
], ],
), ),
),
); );
} }
} }

View File

@@ -144,27 +144,39 @@ class _LogsPageState extends State<LogsPage> {
], ],
), ),
body: logsContent.isNotEmpty body: logsContent.isNotEmpty
? ListView.builder( ? SafeArea(
bottom: false,
child: ListView.separated(
itemCount: logsContent.length, itemCount: logsContent.length,
itemBuilder: (context, index) { itemBuilder: (context, index) {
final log = logsContent[index]; final log = logsContent[index];
if (log['date'] is DateTime) { if (log['date'] is DateTime) {
latestLog ??= log['date']; latestLog ??= log['date'];
} }
return Column( return Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
Row( Row(
children: [ children: [
Padding( Text(
padding: const EdgeInsets.all(8.0),
child: Text(
log['date'].toString(), log['date'].toString(),
style: Theme.of(context).textTheme.titleMedium, style: TextStyle(
fontSize: Theme.of(context)
.textTheme
.titleMedium!
.fontSize,
), ),
), ),
const SizedBox(width: 10),
TextButton.icon( TextButton.icon(
style: TextButton.styleFrom(
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
visualDensity:
VisualDensity(horizontal: -2, vertical: -2),
),
onPressed: () async { onPressed: () async {
await Utils.copyText('```\n${log['body']}\n```', await Utils.copyText('```\n${log['body']}\n```',
needToast: false); needToast: false);
@@ -183,23 +195,28 @@ class _LogsPageState extends State<LogsPage> {
) )
], ],
), ),
Padding( const SizedBox(height: 5),
padding: const EdgeInsets.all(8.0), Card(
child: Card(
elevation: 1, elevation: 1,
clipBehavior: Clip.antiAliasWithSaveLayer, margin: EdgeInsets.zero,
child: Padding( child: Container(
width: double.infinity,
padding: const EdgeInsets.all(12.0), padding: const EdgeInsets.all(12.0),
child: SelectableText(log['body']), child: SelectableText(log['body']),
), ),
), ),
),
const Divider(indent: 12, endIndent: 12),
], ],
),
); );
}, },
separatorBuilder: (context, index) => const Divider(
indent: 12,
endIndent: 12,
height: 24,
),
),
) )
: errorWidget(), : scrollErrorWidget(),
); );
} }
} }

View File

@@ -210,9 +210,9 @@ class _PlaySpeedPageState extends State<PlaySpeedPage> {
const SizedBox(width: 16), const SizedBox(width: 16),
], ],
), ),
body: SingleChildScrollView( body: SafeArea(
child: Column( bottom: false,
crossAxisAlignment: CrossAxisAlignment.start, child: ListView(
children: [ children: [
Padding( Padding(
padding: padding:

View File

@@ -75,22 +75,25 @@ class _SettingsSearchPageState extends State<SettingsSearchPage> {
), ),
), ),
), ),
body: Obx( body: SafeArea(
() => _list.isEmpty bottom: false,
? CustomScrollView( child: CustomScrollView(
slivers: [HttpError()],
)
: CustomScrollView(
slivers: [ slivers: [
SliverWaterfallFlow.extent( Obx(
() => _list.isEmpty
? HttpError()
: SliverPadding(
padding: EdgeInsets.only(
bottom: MediaQuery.paddingOf(context).bottom + 80,
),
sliver: SliverWaterfallFlow.extent(
maxCrossAxisExtent: Grid.smallCardWidth * 2, maxCrossAxisExtent: Grid.smallCardWidth * 2,
children: [ children: [
..._list.map((item) => item.widget), ..._list.map((item) => item.widget),
SizedBox(
height: MediaQuery.paddingOf(context).bottom + 80,
),
], ],
), ),
),
),
], ],
), ),
), ),

View File

@@ -121,13 +121,23 @@ class _SettingPageState extends State<SettingPage> {
: Row( : Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Expanded(flex: 40, child: _buildList), Expanded(
flex: 4,
child: MediaQuery.removePadding(
context: context,
removeRight: true,
child: _buildList,
),
),
VerticalDivider( VerticalDivider(
width: 1, width: 1,
color: Theme.of(context).colorScheme.outline.withOpacity(0.1), color: Theme.of(context).colorScheme.outline.withOpacity(0.1),
), ),
Expanded( Expanded(
flex: 60, flex: 6,
child: MediaQuery.removePadding(
context: context,
removeLeft: true,
child: switch (_type) { child: switch (_type) {
'privacySetting' => PrivacySetting(showAppBar: false), 'privacySetting' => PrivacySetting(showAppBar: false),
'recommendSetting' => RecommendSetting(showAppBar: false), 'recommendSetting' => RecommendSetting(showAppBar: false),
@@ -139,6 +149,7 @@ class _SettingPageState extends State<SettingPage> {
'about' => AboutPage(showAppBar: false), 'about' => AboutPage(showAppBar: false),
_ => const SizedBox.shrink(), _ => const SizedBox.shrink(),
}, },
),
) )
], ],
), ),

View File

@@ -23,7 +23,10 @@ class _SubPageState extends State<SubPage> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar(title: const Text('我的订阅')), appBar: AppBar(title: const Text('我的订阅')),
body: refreshIndicator( body: SafeArea(
top: false,
bottom: false,
child: refreshIndicator(
onRefresh: () async { onRefresh: () async {
await _subController.onRefresh(); await _subController.onRefresh();
}, },
@@ -38,6 +41,7 @@ class _SubPageState extends State<SubPage> {
], ],
), ),
), ),
),
); );
} }

View File

@@ -103,7 +103,7 @@ class _SubDetailPageState extends State<SubDetailPage> {
Widget get _buildCount => SliverToBoxAdapter( Widget get _buildCount => SliverToBoxAdapter(
child: Padding( child: Padding(
padding: const EdgeInsets.only(top: 15, bottom: 8, left: 14), padding: const EdgeInsets.only(top: 12, bottom: 8, left: 14),
child: Obx( child: Obx(
() => Text( () => Text(
'${_subDetailController.mediaCount}条视频', '${_subDetailController.mediaCount}条视频',
@@ -118,7 +118,7 @@ class _SubDetailPageState extends State<SubDetailPage> {
); );
Widget get _buildAppBar => SliverAppBar( Widget get _buildAppBar => SliverAppBar(
expandedHeight: 215 - MediaQuery.paddingOf(context).bottom, expandedHeight: 210 - MediaQuery.paddingOf(context).top,
pinned: true, pinned: true,
title: Obx( title: Obx(
() { () {
@@ -158,7 +158,7 @@ class _SubDetailPageState extends State<SubDetailPage> {
top: kTextTabBarHeight + MediaQuery.of(context).padding.top + 15, top: kTextTabBarHeight + MediaQuery.of(context).padding.top + 15,
left: 12, left: 12,
right: 12, right: 12,
bottom: 20, bottom: 12,
), ),
child: Row( child: Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,

View File

@@ -31,11 +31,7 @@ class _WhisperPageState extends State<WhisperPage> {
child: CustomScrollView( child: CustomScrollView(
physics: const AlwaysScrollableScrollPhysics(), physics: const AlwaysScrollableScrollPhysics(),
slivers: [ slivers: [
SliverSafeArea( _buildTopItems,
top: false,
bottom: false,
sliver: _buildTopItems,
),
Obx(() => _buildBody(_whisperController.loadingState.value)), Obx(() => _buildBody(_whisperController.loadingState.value)),
], ],
), ),
@@ -90,11 +86,14 @@ class _WhisperPageState extends State<WhisperPage> {
}; };
} }
Widget get _buildTopItems => SliverToBoxAdapter( Widget get _buildTopItems => SliverSafeArea(
top: false,
bottom: false,
sliver: SliverToBoxAdapter(
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly, mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: children: List.generate(_whisperController.msgFeedTopItems.length,
List.generate(_whisperController.msgFeedTopItems.length, (index) { (index) {
return GestureDetector( return GestureDetector(
behavior: HitTestBehavior.opaque, behavior: HitTestBehavior.opaque,
child: Padding( child: Padding(
@@ -108,8 +107,8 @@ class _WhisperPageState extends State<WhisperPage> {
() => Badge( () => Badge(
isLabelVisible: isLabelVisible:
_whisperController.unreadCounts[index] > 0, _whisperController.unreadCounts[index] > 0,
label: label: Text(
Text(" ${_whisperController.unreadCounts[index]} "), " ${_whisperController.unreadCounts[index]} "),
alignment: Alignment.topRight, alignment: Alignment.topRight,
child: CircleAvatar( child: CircleAvatar(
radius: 22, radius: 22,
@@ -144,5 +143,6 @@ class _WhisperPageState extends State<WhisperPage> {
); );
}).toList(), }).toList(),
), ),
),
); );
} }

View File

@@ -94,7 +94,10 @@ class _WhisperDetailPageState
), ),
), ),
), ),
body: Column( body: SafeArea(
top: false,
bottom: false,
child: Column(
children: [ children: [
Expanded( Expanded(
child: Listener( child: Listener(
@@ -110,6 +113,7 @@ class _WhisperDetailPageState
buildPanelContainer(Theme.of(context).colorScheme.onInverseSurface), buildPanelContainer(Theme.of(context).colorScheme.onInverseSurface),
], ],
), ),
),
); );
} }