Created
February 11, 2024 09:32
-
-
Save iapicca/51be80efe8eb3bf3110230b5b22b6ec1 to your computer and use it in GitHub Desktop.
scroll view workaround
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// https://codepen.io/sldsrg/pen/RwagmrL | |
import 'dart:async'; | |
import 'package:flutter/gestures.dart'; | |
import 'package:flutter/material.dart'; | |
import 'package:flutter/rendering.dart'; | |
void main() { | |
runApp( | |
MaterialApp( | |
home: PageViewLab(), | |
), | |
); | |
} | |
class PageViewLab extends StatefulWidget { | |
@override | |
_PageViewLabState createState() => _PageViewLabState(); | |
} | |
class _PageViewLabState extends State<PageViewLab> { | |
final sink = StreamController<double>(); | |
final pager = PageController(); | |
@override | |
void initState() { | |
super.initState(); | |
throttle(sink.stream).listen((offset) { | |
pager.animateTo( | |
offset, | |
duration: Duration(milliseconds: 200), | |
curve: Curves.ease, | |
); | |
}); | |
} | |
@override | |
void dispose() { | |
sink.close(); | |
pager.dispose(); | |
super.dispose(); | |
} | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
appBar: AppBar( | |
title: Text('Mouse Wheel with PageView'), | |
), | |
body: Container( | |
constraints: BoxConstraints.expand(), | |
child: Listener( | |
onPointerSignal: _handlePointerSignal, | |
child: _IgnorePointerSignal( | |
child: PageView.builder( | |
controller: pager, | |
scrollDirection: Axis.vertical, | |
itemCount: Colors.primaries.length, | |
itemBuilder: (context, index) { | |
return Padding( | |
padding: const EdgeInsets.all(8.0), | |
child: Container(color: Colors.primaries[index]), | |
); | |
}, | |
), | |
), | |
), | |
), | |
); | |
} | |
Stream<double> throttle(Stream<double> src) async* { | |
double offset = pager.position.pixels; | |
DateTime dt = DateTime.now(); | |
await for (var delta in src) { | |
if (DateTime.now().difference(dt) > Duration(milliseconds: 200)) { | |
offset = pager.position.pixels; | |
} | |
dt = DateTime.now(); | |
offset += delta; | |
yield offset; | |
} | |
} | |
void _handlePointerSignal(PointerSignalEvent e) { | |
if (e is PointerScrollEvent && e.scrollDelta.dy != 0) { | |
sink.add(e.scrollDelta.dy); | |
} | |
} | |
} | |
// workaround https://github.com/flutter/flutter/issues/35723 | |
class _IgnorePointerSignal extends SingleChildRenderObjectWidget { | |
_IgnorePointerSignal({Key key, Widget child}) : super(key: key, child: child); | |
@override | |
RenderObject createRenderObject(_) => _IgnorePointerSignalRenderObject(); | |
} | |
class _IgnorePointerSignalRenderObject extends RenderProxyBox { | |
@override | |
bool hitTest(BoxHitTestResult result, {Offset position}) { | |
final res = super.hitTest(result, position: position); | |
result.path.forEach((item) { | |
final target = item.target; | |
if (target is RenderPointerListener) { | |
target.onPointerSignal = null; | |
} | |
}); | |
return res; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment