Fix the mouse scrolling issue when multiple scroll lists are nested.

This commit is contained in:
2025-04-05 17:45:29 +08:00
parent d91bca6913
commit 118941f239
2 changed files with 65 additions and 11 deletions

View File

@@ -51,10 +51,32 @@ class _SmoothScrollProviderState extends State<SmoothScrollProvider> {
static bool _isMouseScroll = App.isDesktop; static bool _isMouseScroll = App.isDesktop;
late int id;
static int _id = 0;
var activeChildren = <int>{};
ScrollState? parent;
@override @override
void initState() { void initState() {
_controller = widget.controller ?? ScrollController(); _controller = widget.controller ?? ScrollController();
super.initState(); super.initState();
id = _id;
_id++;
}
@override
void didChangeDependencies() {
parent = ScrollState.maybeOf(context);
super.didChangeDependencies();
}
@override
void dispose() {
parent?.onChildInactive(id);
super.dispose();
} }
@override @override
@@ -66,8 +88,7 @@ class _SmoothScrollProviderState extends State<SmoothScrollProvider> {
const BouncingScrollPhysics(), const BouncingScrollPhysics(),
); );
} }
return Listener( var child = Listener(
behavior: HitTestBehavior.translucent,
onPointerDown: (event) { onPointerDown: (event) {
_futurePosition = null; _futurePosition = null;
if (_isMouseScroll) { if (_isMouseScroll) {
@@ -77,6 +98,9 @@ class _SmoothScrollProviderState extends State<SmoothScrollProvider> {
} }
}, },
onPointerSignal: (pointerSignal) { onPointerSignal: (pointerSignal) {
if (activeChildren.isNotEmpty) {
return;
}
if (pointerSignal is PointerScrollEvent) { if (pointerSignal is PointerScrollEvent) {
if (HardwareKeyboard.instance.isShiftPressed) { if (HardwareKeyboard.instance.isShiftPressed) {
return; return;
@@ -113,8 +137,14 @@ class _SmoothScrollProviderState extends State<SmoothScrollProvider> {
}); });
} }
}, },
child: ScrollControllerProvider._( child: ScrollState._(
controller: _controller, controller: _controller,
onChildActive: (id) {
activeChildren.add(id);
},
onChildInactive: (id) {
activeChildren.remove(id);
},
child: widget.builder( child: widget.builder(
context, context,
_controller, _controller,
@@ -124,25 +154,49 @@ class _SmoothScrollProviderState extends State<SmoothScrollProvider> {
), ),
), ),
); );
if (parent != null) {
return MouseRegion(
onEnter: (_) {
parent!.onChildActive(id);
},
onExit: (_) {
parent!.onChildInactive(id);
},
child: child,
);
}
return child;
} }
} }
class ScrollControllerProvider extends InheritedWidget { class ScrollState extends InheritedWidget {
const ScrollControllerProvider._({ const ScrollState._({
required this.controller, required this.controller,
required super.child, required super.child,
required this.onChildActive,
required this.onChildInactive,
}); });
final ScrollController controller; final ScrollController controller;
static ScrollController of(BuildContext context) { final void Function(int id) onChildActive;
final ScrollControllerProvider? provider =
context.dependOnInheritedWidgetOfExactType<ScrollControllerProvider>(); final void Function(int id) onChildInactive;
return provider!.controller;
static ScrollState of(BuildContext context) {
final ScrollState? provider =
context.dependOnInheritedWidgetOfExactType<ScrollState>();
return provider!;
}
static ScrollState? maybeOf(BuildContext context) {
return context.dependOnInheritedWidgetOfExactType<ScrollState>();
} }
@override @override
bool updateShouldNotify(ScrollControllerProvider oldWidget) { bool updateShouldNotify(ScrollState oldWidget) {
return oldWidget.controller != controller; return oldWidget.controller != controller;
} }
} }

View File

@@ -942,7 +942,7 @@ class _ImageFavoritesState extends State<ImageFavorites> {
displayType = type; displayType = type;
}); });
await Future.delayed(const Duration(milliseconds: 20)); await Future.delayed(const Duration(milliseconds: 20));
var scrollController = ScrollControllerProvider.of(context); var scrollController = ScrollState.of(context).controller;
scrollController.animateTo( scrollController.animateTo(
scrollController.position.maxScrollExtent, scrollController.position.maxScrollExtent,
duration: const Duration(milliseconds: 200), duration: const Duration(milliseconds: 200),