diff --git a/lib/common/widgets/custom_sliver_persistent_header_delegate.dart b/lib/common/widgets/custom_sliver_persistent_header_delegate.dart index b699c4afa..777aea679 100644 --- a/lib/common/widgets/custom_sliver_persistent_header_delegate.dart +++ b/lib/common/widgets/custom_sliver_persistent_header_delegate.dart @@ -1,18 +1,15 @@ -import 'dart:io' show Platform; - import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart' show RenderProxyBox; class CustomSliverPersistentHeaderDelegate extends SliverPersistentHeaderDelegate { const CustomSliverPersistentHeaderDelegate({ required this.child, - required this.bgColor, - double extent = 45, + this.bgColor, + this.extent = 45, this.needRebuild = false, - }) : _minExtent = extent, - _maxExtent = extent; - final double _minExtent; - final double _maxExtent; + }); + final double extent; final Widget child; final Color? bgColor; final bool needRebuild; @@ -26,31 +23,16 @@ class CustomSliverPersistentHeaderDelegate //创建child子组件 //shrinkOffset:child偏移值minExtent~maxExtent //overlapsContent:SliverPersistentHeader覆盖其他子组件返回true,否则返回false - return bgColor != null - ? DecoratedBox( - decoration: BoxDecoration( - color: bgColor, - boxShadow: Platform.isIOS - ? null - : [ - BoxShadow( - color: bgColor!, - offset: const Offset(0, -1), - ), - ], - ), - child: child, - ) - : child; + return _DecoratedBox(color: bgColor, child: child); } //SliverPersistentHeader最大高度 @override - double get maxExtent => _maxExtent; + double get maxExtent => extent; //SliverPersistentHeader最小高度 @override - double get minExtent => _minExtent; + double get minExtent => extent; @override bool shouldRebuild(CustomSliverPersistentHeaderDelegate oldDelegate) { @@ -58,3 +40,62 @@ class CustomSliverPersistentHeaderDelegate (needRebuild && oldDelegate.child != child); } } + +class _DecoratedBox extends SingleChildRenderObjectWidget { + const _DecoratedBox({ + this.color, + super.child, + }); + + final Color? color; + + @override + RenderObject createRenderObject(BuildContext context) { + return _RenderDecoratedBox(color: color); + } + + @override + void updateRenderObject( + BuildContext context, + _RenderDecoratedBox renderObject, + ) { + renderObject.color = color; + } +} + +class _RenderDecoratedBox extends RenderProxyBox { + _RenderDecoratedBox({ + Color? color, + }) : _color = color; + + Color? _color; + Color? get color => _color; + set color(Color? value) { + if (_color == value) return; + _color = value; + markNeedsPaint(); + } + + @override + void paint(PaintingContext context, Offset offset) { + if (_color case final color?) { + final size = this.size; + context.canvas.drawRect( + Rect.fromLTWH( + offset.dx, + offset.dy - 2, + size.width, + size.height + 2, + ), + Paint()..color = color, + ); + } + super.paint(context, offset); + } + + @override + bool hitTestSelf(Offset position) => true; + + @override + bool get isRepaintBoundary => true; +} diff --git a/lib/pages/dynamics_topic/view.dart b/lib/pages/dynamics_topic/view.dart index d1f3420c9..f89bb8d27 100644 --- a/lib/pages/dynamics_topic/view.dart +++ b/lib/pages/dynamics_topic/view.dart @@ -81,13 +81,14 @@ class _DynTopicPageState extends State with DynMixin { return SliverPersistentHeader( pinned: true, delegate: CustomSliverPersistentHeaderDelegate( - extent: 30, + extent: 36, needRebuild: true, bgColor: theme.colorScheme.surface, child: Container( - height: 30, + height: 36, padding: EdgeInsets.only( left: 12 + padding.left, + top: 6, bottom: 6, ), child: Builder( @@ -101,16 +102,14 @@ class _DynTopicPageState extends State with DynMixin { minHeight: 24, ), tapTargetSize: MaterialTapTargetSize.shrinkWrap, - borderRadius: const BorderRadius.all( - Radius.circular(25), - ), + borderRadius: const .all(.circular(25)), onPressed: (index) { _controller.onSort(allSortBy[index].sortBy!); (context as Element).markNeedsBuild(); }, - isSelected: allSortBy.map((e) { - return e.sortBy == _controller.sortBy; - }).toList(), + isSelected: allSortBy + .map((e) => e.sortBy == _controller.sortBy) + .toList(), children: allSortBy.map((e) { return Text( e.sortName!, diff --git a/lib/pages/live_dm_block/view.dart b/lib/pages/live_dm_block/view.dart index 2bd5307d8..f7f097d89 100644 --- a/lib/pages/live_dm_block/view.dart +++ b/lib/pages/live_dm_block/view.dart @@ -107,7 +107,6 @@ class _LiveDmBlockPageState extends State { delegate: CustomSliverPersistentHeaderDelegate( extent: 48, child: tabBar, - bgColor: null, ), ), ), diff --git a/lib/pages/member_favorite/view.dart b/lib/pages/member_favorite/view.dart index 75fe2d4fd..8962a092e 100644 --- a/lib/pages/member_favorite/view.dart +++ b/lib/pages/member_favorite/view.dart @@ -160,7 +160,6 @@ class _MemberFavoriteState extends State }, ), ), - bgColor: null, ), ), Obx(() { diff --git a/lib/pages/video/widgets/header_control.dart b/lib/pages/video/widgets/header_control.dart index 0fcf3b14a..eae0c26fe 100644 --- a/lib/pages/video/widgets/header_control.dart +++ b/lib/pages/video/widgets/header_control.dart @@ -6,7 +6,6 @@ import 'dart:math'; import 'package:PiliPlus/common/constants.dart'; import 'package:PiliPlus/common/widgets/button/icon_button.dart'; import 'package:PiliPlus/common/widgets/custom_icon.dart'; -import 'package:PiliPlus/common/widgets/custom_sliver_persistent_header_delegate.dart'; import 'package:PiliPlus/common/widgets/dialog/report.dart'; import 'package:PiliPlus/common/widgets/marquee.dart'; import 'package:PiliPlus/http/danmaku.dart'; @@ -1580,49 +1579,55 @@ class HeaderControlState extends State if (ctr == null) return; showBottomSheet((context, setState) { final theme = Theme.of(context); - return Padding( - padding: const EdgeInsets.all(12), - child: Material( - clipBehavior: Clip.hardEdge, + return Container( + margin: const EdgeInsets.all(12), + decoration: BoxDecoration( color: theme.colorScheme.surface, borderRadius: const BorderRadius.all(Radius.circular(12)), - child: CustomScrollView( - slivers: [ - SliverPersistentHeader( - pinned: true, - delegate: CustomSliverPersistentHeaderDelegate( - child: Container( - height: 45, - padding: const EdgeInsets.symmetric(horizontal: 14), - decoration: BoxDecoration( - border: Border( - bottom: BorderSide( - color: theme.colorScheme.outline.withValues( - alpha: 0.1, - ), - ), - ), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const Text('弹幕列表'), - iconButton( - onPressed: () => setState(() {}), - icon: const Icon(Icons.refresh), - ), - ], - ), + ), + child: Column( + children: [ + Container( + height: 45, + padding: const EdgeInsets.symmetric(horizontal: 14), + decoration: BoxDecoration( + border: Border( + bottom: BorderSide( + color: theme.colorScheme.outline.withValues(alpha: 0.1), ), - bgColor: theme.colorScheme.surface, ), ), - ?_buildDanmakuList(ctr.staticDanmaku.nonNulls.toList()), - ?_buildDanmakuList(ctr.scrollDanmaku.expand((e) => e).toList()), - ?_buildDanmakuList(ctr.specialDanmaku.toList()), - const SliverToBoxAdapter(child: SizedBox(height: 12)), - ], - ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const Text('弹幕列表'), + iconButton( + onPressed: () => setState(() {}), + icon: const Icon(Icons.refresh), + ), + ], + ), + ), + Expanded( + child: Material( + type: .transparency, + clipBehavior: .hardEdge, + borderRadius: const BorderRadius.vertical( + bottom: Radius.circular(12), + ), + child: CustomScrollView( + slivers: [ + ?_buildDanmakuList(ctr.staticDanmaku.nonNulls.toList()), + ?_buildDanmakuList( + ctr.scrollDanmaku.expand((e) => e).toList(), + ), + ?_buildDanmakuList(ctr.specialDanmaku.toList()), + const SliverToBoxAdapter(child: SizedBox(height: 12)), + ], + ), + ), + ), + ], ), ); });