diff --git a/changelog/v7.4.8+147.md b/changelog/v7.4.8+147.md new file mode 100644 index 00000000..bcae8e63 --- /dev/null +++ b/changelog/v7.4.8+147.md @@ -0,0 +1,5 @@ +- 修复在部分场景下,自动阅读模式无法滚动到末尾的bug + +------------------------------------------------------------------------------------------ + +- Fix the bug that auto reading mode cannot scroll to the end in some scenes \ No newline at end of file diff --git a/lib/src/pages/read/layout/horizontal_list/horizontal_list_layout_logic.dart b/lib/src/pages/read/layout/horizontal_list/horizontal_list_layout_logic.dart index 63c010f6..49a99258 100644 --- a/lib/src/pages/read/layout/horizontal_list/horizontal_list_layout_logic.dart +++ b/lib/src/pages/read/layout/horizontal_list/horizontal_list_layout_logic.dart @@ -153,14 +153,12 @@ class HorizontalListLayoutLogic extends BaseLayoutLogic { void _enterAutoModeByScroll() { int restPageCount = readPageState.readPageInfo.pageCount - readPageState.readPageInfo.currentImageIndex - 1; - double offset = restPageCount * screenHeight; double totalTime = restPageCount * ReadSetting.autoModeInterval.value; readPageLogic.toggleMenu(); state.itemScrollController - .scrollOffset( - offset: offset, + .scrollToEnd( duration: Duration(milliseconds: (totalTime * 1000).toInt()), ) .then((_) => readPageLogic.closeAutoMode()); diff --git a/lib/src/pages/read/layout/vertical_list/vertical_list_layout_logic.dart b/lib/src/pages/read/layout/vertical_list/vertical_list_layout_logic.dart index 95a6fa6f..bb4912ab 100644 --- a/lib/src/pages/read/layout/vertical_list/vertical_list_layout_logic.dart +++ b/lib/src/pages/read/layout/vertical_list/vertical_list_layout_logic.dart @@ -144,14 +144,12 @@ class VerticalListLayoutLogic extends BaseLayoutLogic { void _enterAutoModeByScroll() { int restPageCount = readPageState.readPageInfo.pageCount - readPageState.readPageInfo.currentImageIndex - 1; - double offset = restPageCount * screenHeight; double totalTime = restPageCount * ReadSetting.autoModeInterval.value; readPageLogic.toggleMenu(); state.itemScrollController - .scrollOffset( - offset: offset, + .scrollToEnd( duration: Duration(milliseconds: (totalTime * 1000).toInt()), ) .then((_) => readPageLogic.closeAutoMode()); diff --git a/lib/src/pages/read/widget/eh_scrollable_positioned_list.dart b/lib/src/pages/read/widget/eh_scrollable_positioned_list.dart index d5da59c3..8479bff8 100644 --- a/lib/src/pages/read/widget/eh_scrollable_positioned_list.dart +++ b/lib/src/pages/read/widget/eh_scrollable_positioned_list.dart @@ -245,6 +245,21 @@ class EHItemScrollController { ); } + Future scrollToEnd({ + required Duration duration, + Curve curve = Curves.linear, + List opacityAnimationWeights = const [40, 20, 40], + }) { + assert(_scrollableListState != null); + assert(opacityAnimationWeights.length == 3); + assert(duration > Duration.zero); + return _scrollableListState!._scrollToEnd( + duration: duration, + curve: curve, + opacityAnimationWeights: opacityAnimationWeights, + ); + } + void _attach(_EHScrollablePositionedListState scrollableListState) { assert(_scrollableListState == null); _scrollableListState = scrollableListState; @@ -480,6 +495,33 @@ class _EHScrollablePositionedListState extends State } } + Future _scrollToEnd({ + required Duration duration, + Curve curve = Curves.linear, + required List opacityAnimationWeights, + }) async { + if (_isTransitioning) { + _stopScroll(canceled: true); + SchedulerBinding.instance.addPostFrameCallback((_) { + _startScrollOffset( + offset: primary.scrollController.position.maxScrollExtent - primary.scrollController.position.pixels, + alignment: 0, + duration: duration, + curve: curve, + opacityAnimationWeights: opacityAnimationWeights, + ); + }); + } else { + await _startScrollOffset( + offset: primary.scrollController.position.maxScrollExtent - primary.scrollController.position.pixels, + alignment: 0, + duration: duration, + curve: curve, + opacityAnimationWeights: opacityAnimationWeights, + ); + } + } + Future _startScroll({ required int index, required double alignment, @@ -488,15 +530,13 @@ class _EHScrollablePositionedListState extends State required List opacityAnimationWeights, }) async { final direction = index > primary.target ? 1 : -1; - final itemPosition = primary.itemPositionsNotifier.itemPositions.value - .firstWhereOrNull((ItemPosition itemPosition) => itemPosition.index == index); + final itemPosition = + primary.itemPositionsNotifier.itemPositions.value.firstWhereOrNull((ItemPosition itemPosition) => itemPosition.index == index); if (itemPosition != null) { // Scroll directly. final localScrollAmount = itemPosition.itemLeadingEdge * primary.scrollController.position.viewportDimension; await primary.scrollController.animateTo( - primary.scrollController.offset + - localScrollAmount - - alignment * primary.scrollController.position.viewportDimension, + primary.scrollController.offset + localScrollAmount - alignment * primary.scrollController.position.viewportDimension, duration: duration, curve: curve); } else { @@ -507,14 +547,13 @@ class _EHScrollablePositionedListState extends State SchedulerBinding.instance.addPostFrameCallback((_) { startAnimationCallback = () {}; - opacity.parent = _opacityAnimation(opacityAnimationWeights) - .animate(AnimationController(vsync: this, duration: duration)..forward()); + opacity.parent = _opacityAnimation(opacityAnimationWeights).animate(AnimationController(vsync: this, duration: duration)..forward()); secondary.scrollController.jumpTo(-direction * (_screenScrollCount * primary.scrollController.position.viewportDimension - alignment * secondary.scrollController.position.viewportDimension)); - startCompleter.complete(primary.scrollController - .animateTo(primary.scrollController.offset + direction * scrollAmount, duration: duration, curve: curve)); + startCompleter.complete( + primary.scrollController.animateTo(primary.scrollController.offset + direction * scrollAmount, duration: duration, curve: curve)); endCompleter.complete(secondary.scrollController.animateTo(0, duration: duration, curve: curve)); }); }; @@ -576,8 +615,7 @@ class _EHScrollablePositionedListState extends State const endOpacity = 1.0; return TweenSequence(>[ TweenSequenceItem(tween: ConstantTween(startOpacity), weight: opacityAnimationWeights[0]), - TweenSequenceItem( - tween: Tween(begin: startOpacity, end: endOpacity), weight: opacityAnimationWeights[1]), + TweenSequenceItem(tween: Tween(begin: startOpacity, end: endOpacity), weight: opacityAnimationWeights[1]), TweenSequenceItem(tween: ConstantTween(endOpacity), weight: opacityAnimationWeights[2]), ]); } @@ -586,8 +624,8 @@ class _EHScrollablePositionedListState extends State final itemPositions = primary.itemPositionsNotifier.itemPositions.value .where((ItemPosition position) => position.itemLeadingEdge < 1 && position.itemTrailingEdge > 0); if (itemPositions.isNotEmpty) { - PageStorage.of(context).writeState(context, - itemPositions.reduce((value, element) => value.itemLeadingEdge < element.itemLeadingEdge ? value : element)); + PageStorage.of(context) + .writeState(context, itemPositions.reduce((value, element) => value.itemLeadingEdge < element.itemLeadingEdge ? value : element)); } widget.itemPositionsNotifier?.itemPositions.value = itemPositions; }