From 690c4f57865babd1d4b9ba56cd69a5414f6a0953 Mon Sep 17 00:00:00 2001 From: My-Responsitories <107370289+My-Responsitories@users.noreply.github.com> Date: Tue, 12 Aug 2025 17:06:33 +0800 Subject: [PATCH] feat: grid jump to index (#1004) --- lib/pages/dynamics_create/view.dart | 2 +- lib/pages/member_video/view.dart | 33 +++++++++++++++++++++++------ lib/pages/video/reply_new/view.dart | 2 +- lib/utils/grid.dart | 13 +++++++++--- 4 files changed, 38 insertions(+), 12 deletions(-) diff --git a/lib/pages/dynamics_create/view.dart b/lib/pages/dynamics_create/view.dart index 4efcb6aa..9dbdf31d 100644 --- a/lib/pages/dynamics_create/view.dart +++ b/lib/pages/dynamics_create/view.dart @@ -595,7 +595,7 @@ class _CreateDynPanelState extends CommonRichTextPubPageState { height: height, child: GridView( padding: const EdgeInsets.only(left: 12, bottom: 12, right: 12), - gridDelegate: const SliverGridDelegateWithExtentAndRatio( + gridDelegate: SliverGridDelegateWithExtentAndRatio( maxCrossAxisExtent: 65, mainAxisSpacing: 12, crossAxisSpacing: 12, diff --git a/lib/pages/member_video/view.dart b/lib/pages/member_video/view.dart index b8d049f6..f361cf13 100644 --- a/lib/pages/member_video/view.dart +++ b/lib/pages/member_video/view.dart @@ -42,6 +42,8 @@ class _MemberVideoState extends State @override bool get wantKeepAlive => true; + late final gridDelegate = Grid.videoCardHDelegate(context); + late final _controller = Get.put( MemberVideoCtr( type: widget.type, @@ -89,12 +91,29 @@ class _MemberVideoState extends State top: false, left: false, child: FloatingActionButton.extended( - onPressed: () => _controller - ..isLocating.value = true - ..lastAid = _controller.fromViewAid - ..page = 0 - ..loadingState.value = LoadingState.loading() - ..queryData(), + onPressed: () { + final fromViewAid = _controller.fromViewAid; + _controller + ..isLocating.value = true + ..lastAid = fromViewAid; + final locatedIndex = _controller + .loadingState + .value + .dataOrNull + ?.indexWhere((i) => i.param == fromViewAid); + if (locatedIndex == null || locatedIndex == -1) { + _controller + ..page = 0 + ..loadingState.value = LoadingState.loading() + ..queryData(); + } else { + PrimaryScrollController.of(context).jumpTo( + gridDelegate.layoutCache! + .getGeometryForChildIndex(locatedIndex) + .scrollOffset, + ); + } + }, label: const Text('定位至上次观看'), ), ), @@ -217,7 +236,7 @@ class _MemberVideoState extends State ), ), SliverGrid( - gridDelegate: Grid.videoCardHDelegate(context), + gridDelegate: gridDelegate, delegate: SliverChildBuilderDelegate( (context, index) { if (widget.type != ContributeType.season && diff --git a/lib/pages/video/reply_new/view.dart b/lib/pages/video/reply_new/view.dart index 8bc460e2..214b01e2 100644 --- a/lib/pages/video/reply_new/view.dart +++ b/lib/pages/video/reply_new/view.dart @@ -301,7 +301,7 @@ class _ReplyPageState extends CommonRichTextPubPageState { height: height, child: GridView( padding: const EdgeInsets.only(left: 12, bottom: 12, right: 12), - gridDelegate: const SliverGridDelegateWithExtentAndRatio( + gridDelegate: SliverGridDelegateWithExtentAndRatio( maxCrossAxisExtent: 65, mainAxisSpacing: 12, crossAxisSpacing: 12, diff --git a/lib/utils/grid.dart b/lib/utils/grid.dart index f2193ab9..f8caf879 100644 --- a/lib/utils/grid.dart +++ b/lib/utils/grid.dart @@ -26,7 +26,7 @@ class SliverGridDelegateWithExtentAndRatio extends SliverGridDelegate { /// The [maxCrossAxisExtent], [mainAxisExtent], [mainAxisSpacing], /// and [crossAxisSpacing] arguments must not be negative. /// The [childAspectRatio] argument must be greater than zero. - const SliverGridDelegateWithExtentAndRatio({ + SliverGridDelegateWithExtentAndRatio({ required this.maxCrossAxisExtent, this.mainAxisSpacing = 0.0, this.crossAxisSpacing = 0.0, @@ -76,9 +76,13 @@ class SliverGridDelegateWithExtentAndRatio extends SliverGridDelegate { return true; } + SliverGridLayout? layoutCache; + @override SliverGridLayout getLayout(SliverConstraints constraints) { + // invoked before each frame assert(_debugAssertIsValid(constraints.crossAxisExtent)); + if (layoutCache != null) return layoutCache!; int crossAxisCount = ((constraints.crossAxisExtent - crossAxisSpacing) / (maxCrossAxisExtent + crossAxisSpacing)) @@ -95,7 +99,7 @@ class SliverGridDelegateWithExtentAndRatio extends SliverGridDelegate { minHeight, childCrossAxisExtent / childAspectRatio + mainAxisExtent, ); - return SliverGridRegularTileLayout( + return layoutCache = SliverGridRegularTileLayout( crossAxisCount: crossAxisCount, mainAxisStride: childMainAxisExtent + mainAxisSpacing, crossAxisStride: childCrossAxisExtent + crossAxisSpacing, @@ -107,10 +111,13 @@ class SliverGridDelegateWithExtentAndRatio extends SliverGridDelegate { @override bool shouldRelayout(SliverGridDelegateWithExtentAndRatio oldDelegate) { - return oldDelegate.maxCrossAxisExtent != maxCrossAxisExtent || + final flag = + oldDelegate.maxCrossAxisExtent != maxCrossAxisExtent || oldDelegate.mainAxisSpacing != mainAxisSpacing || oldDelegate.crossAxisSpacing != crossAxisSpacing || oldDelegate.childAspectRatio != childAspectRatio || oldDelegate.mainAxisExtent != mainAxisExtent; + if (flag) layoutCache = null; + return flag; } }