From 3ddb4bec3a1fa983b6bb6d294b5c19b4d4a37628 Mon Sep 17 00:00:00 2001 From: xuelong Date: Thu, 12 Jan 2023 16:54:00 +0800 Subject: [PATCH] fix: The indicator does not retract when the height of the list changes (https://github.com/xuelongqy/flutter_easy_refresh/issues/618). --- CHANGELOG.md | 3 ++ example/lib/page/style/halloween_page.dart | 4 +- .../Flutter/GeneratedPluginRegistrant.swift | 2 + example/pubspec.yaml | 2 +- .../flutter/generated_plugin_registrant.cc | 3 ++ .../windows/flutter/generated_plugins.cmake | 1 + lib/src/notifier/indicator_notifier.dart | 39 +++++++++++-------- lib/src/physics/scroll_physics.dart | 3 ++ 8 files changed, 37 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8c508f5b..d62d1f34 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +## Next +- fix: The indicator does not retract when the height of the list changes [#618](https://github.com/xuelongqy/flutter_easy_refresh/issues/618). + ## 3.2.2+1 - fix: CupertinoActivityIndicator renamed to avoid conflicts. diff --git a/example/lib/page/style/halloween_page.dart b/example/lib/page/style/halloween_page.dart index 4caa6dbc..012662ad 100644 --- a/example/lib/page/style/halloween_page.dart +++ b/example/lib/page/style/halloween_page.dart @@ -35,10 +35,10 @@ class _HalloweenPageState extends State { return Scaffold( body: EasyRefresh( controller: _controller, - header: HalloweenHeader( + header: const HalloweenHeader( position: IndicatorPosition.locator, ), - footer: HalloweenFooter( + footer: const HalloweenFooter( position: IndicatorPosition.locator, ), onRefresh: () async { diff --git a/example/macos/Flutter/GeneratedPluginRegistrant.swift b/example/macos/Flutter/GeneratedPluginRegistrant.swift index 8236f572..f6334d64 100644 --- a/example/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/example/macos/Flutter/GeneratedPluginRegistrant.swift @@ -5,8 +5,10 @@ import FlutterMacOS import Foundation +import rive_common import url_launcher_macos func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + RivePlugin.register(with: registry.registrar(forPlugin: "RivePlugin")) UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) } diff --git a/example/pubspec.yaml b/example/pubspec.yaml index a14c08c0..a3a9421d 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -27,7 +27,7 @@ dependencies: get: ^4.6.5 convert: ^3.1.1 carousel_slider: ^4.2.1 - rive: 0.9.1 + rive: ^0.10.1 qr_flutter: ^4.0.0 flutter_svg: ^1.1.6 flutter_sticky_header: ^0.6.5 diff --git a/example/windows/flutter/generated_plugin_registrant.cc b/example/windows/flutter/generated_plugin_registrant.cc index 4f788487..72ff4b78 100644 --- a/example/windows/flutter/generated_plugin_registrant.cc +++ b/example/windows/flutter/generated_plugin_registrant.cc @@ -6,9 +6,12 @@ #include "generated_plugin_registrant.h" +#include #include void RegisterPlugins(flutter::PluginRegistry* registry) { + RivePluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("RivePlugin")); UrlLauncherWindowsRegisterWithRegistrar( registry->GetRegistrarForPlugin("UrlLauncherWindows")); } diff --git a/example/windows/flutter/generated_plugins.cmake b/example/windows/flutter/generated_plugins.cmake index 88b22e5c..e141d513 100644 --- a/example/windows/flutter/generated_plugins.cmake +++ b/example/windows/flutter/generated_plugins.cmake @@ -3,6 +3,7 @@ # list(APPEND FLUTTER_PLUGIN_LIST + rive_common url_launcher_windows ) diff --git a/lib/src/notifier/indicator_notifier.dart b/lib/src/notifier/indicator_notifier.dart index db2a96fc..40dc62ba 100644 --- a/lib/src/notifier/indicator_notifier.dart +++ b/lib/src/notifier/indicator_notifier.dart @@ -139,7 +139,7 @@ abstract class IndicatorNotifier extends ChangeNotifier { double get offset => _offset; /// The current scroll position. - ScrollMetrics get position => _position; + ScrollMetrics get position => _position!; set position(ScrollMetrics value) { if (value.isNestedOuter) { @@ -152,9 +152,14 @@ abstract class IndicatorNotifier extends ChangeNotifier { _viewportDimension = null; } _position = value; + _lastMaxScrollExtent = value.maxScrollExtent; } - late ScrollMetrics _position; + ScrollMetrics? _position; + + /// Cache maxScrollExtent. + /// Used to compare the last value. + double? _lastMaxScrollExtent; /// The current scroll velocity. double _velocity = 0; @@ -422,7 +427,7 @@ abstract class IndicatorNotifier extends ChangeNotifier { /// Animation listener for [clamping]. void _clampingTick() { final mOffset = calculateOffsetWithPixels( - _position, _clampingAnimationController!.value); + position, _clampingAnimationController!.value); if (hasSecondary && !noMoreLocked && mOffset > secondaryDimension && @@ -509,7 +514,7 @@ abstract class IndicatorNotifier extends ChangeNotifier { if (_mode == IndicatorMode.done || // Handling infinite scroll (infiniteOffset != null && - (!_position.isNestedOuter && edgeOffset < infiniteOffset!) && + (!position.isNestedOuter && edgeOffset < infiniteOffset!) && !bySimulation && !_infiniteExclude(position, value))) { // Update mode @@ -571,9 +576,9 @@ abstract class IndicatorNotifier extends ChangeNotifier { } // Infinite scroll if (infiniteOffset != null && - (!_position.isNestedOuter && edgeOffset < infiniteOffset!)) { + (!position.isNestedOuter && edgeOffset < infiniteOffset!)) { if (_mode == IndicatorMode.done && - _position.maxScrollExtent != _position.minScrollExtent) { + position.maxScrollExtent != position.minScrollExtent) { // The state does not change until the end return; } else { @@ -746,7 +751,7 @@ abstract class IndicatorNotifier extends ChangeNotifier { if (clamping && !userOffsetNotifier.value) { // Sucks. When clamping, the position will not change after the task is completed. // Temporary solution like this, there is a better way to replace. - double pixels = _position.pixels; + double pixels = position.pixels; const tiny = 0.001; pixels -= tiny; (_position as ScrollPosition).jumpTo(pixels); @@ -800,7 +805,7 @@ abstract class IndicatorNotifier extends ChangeNotifier { // Actively update the offset if the user does not release if (!clamping && userOffsetNotifier.value) { Future(() { - _updateOffset(_position, _position.pixels, false); + _updateOffset(position, position.pixels, false); }); } } @@ -958,7 +963,7 @@ class HeaderNotifier extends IndicatorNotifier { /// See [IndicatorNotifier.edgeOffset]. @override - double get edgeOffset => _position.pixels; + double get edgeOffset => position.pixels; @override bool _infiniteExclude(ScrollMetrics position, double value) { @@ -988,21 +993,21 @@ class HeaderNotifier extends IndicatorNotifier { scrollController .jumpTo(scrollController.positions.first.minScrollExtent); } else { - (_position as ScrollPosition).jumpTo(_position.minScrollExtent); + (_position as ScrollPosition).jumpTo(position.minScrollExtent); } } if (clamping) { if (duration == null) { _offset = offset; _mode = mode; - _updateBySimulation(_position, 0); + _updateBySimulation(position, 0); } else { userOffsetNotifier.value = true; _clampingAnimationController!.value = position.minScrollExtent; await _clampingAnimationController! .animateTo(scrollTo, duration: duration, curve: curve); userOffsetNotifier.value = false; - _updateBySimulation(_position, 0); + _updateBySimulation(position, 0); } } else { if (_position is ScrollPosition) { @@ -1122,7 +1127,7 @@ class FooterNotifier extends IndicatorNotifier { /// See [IndicatorNotifier.edgeOffset]. @override - double get edgeOffset => _position.maxScrollExtent - _position.pixels; + double get edgeOffset => position.maxScrollExtent - position.pixels; @override bool _infiniteExclude(ScrollMetrics position, double value) { @@ -1145,28 +1150,28 @@ class FooterNotifier extends IndicatorNotifier { } catch (_) { return; } - final scrollTo = _position.maxScrollExtent + offset; + final scrollTo = position.maxScrollExtent + offset; _releaseOffset = offset; if (jumpToEdge) { if (scrollController != null) { scrollController .jumpTo(scrollController.positions.first.maxScrollExtent); } else { - (_position as ScrollPosition).jumpTo(_position.maxScrollExtent); + (_position as ScrollPosition).jumpTo(position.maxScrollExtent); } } if (clamping) { if (duration == null) { _offset = offset; _mode = mode; - _updateBySimulation(_position, 0); + _updateBySimulation(position, 0); } else { userOffsetNotifier.value = true; _clampingAnimationController!.value = position.maxScrollExtent; await _clampingAnimationController! .animateTo(scrollTo, duration: duration, curve: curve); userOffsetNotifier.value = false; - _updateBySimulation(_position, 0); + _updateBySimulation(position, 0); } } else { if (_position is ScrollPosition) { diff --git a/lib/src/physics/scroll_physics.dart b/lib/src/physics/scroll_physics.dart index 4a8438b4..e916561c 100644 --- a/lib/src/physics/scroll_physics.dart +++ b/lib/src/physics/scroll_physics.dart @@ -439,6 +439,8 @@ class _ERScrollPhysics extends BouncingScrollPhysics { // User stopped scrolling. final oldUserOffset = userOffsetNotifier.value; userOffsetNotifier.value = false; + final oldMaxScrollExtent = + headerNotifier._lastMaxScrollExtent ?? position.maxScrollExtent; // Simulation update. headerNotifier._updateBySimulation(position, velocity); footerNotifier._updateBySimulation(position, velocity); @@ -462,6 +464,7 @@ class _ERScrollPhysics extends BouncingScrollPhysics { footerNotifier._mode == IndicatorMode.secondaryOpen); bool secondary = hSecondary || fSecondary; if (velocity.abs() >= tolerance.velocity || + (oldMaxScrollExtent != position.maxScrollExtent) || (position.outOfRange || (secondary && oldUserOffset)) && (oldUserOffset || _headerSimulationCreationState.value.needCreation(hState) ||