最近我陷入了类似的情况,经过一些研究并阅读了有关手势如何在颤动下工作的信息,我找到了一个足够好的工作解决方案。
因此,我使用了 RawGestureDetector ,它为您提供了手势的低级窗口小部件处理功能,并通过将它们的physics
设置为NeverScrollableScrollPhysics
来禁用了PageView和ListView的滚动。这意味着使用它们各自的控制器PageViewController
和ScrollController
滚动这些小部件。现在,根据ListView的位置和状态,选择两者中的一个活动控制器并使用该控制器拖动。主类看起来像这样。
void main() => runApp(App());
class App extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(home: Scaffold(appBar: AppBar(),body: NestedContainerWidget()));
}
}
class NestedContainerWidget extends StatefulWidget {
@override
_NestedContainerWidgetState createState() => _NestedContainerWidgetState();
}
class _NestedContainerWidgetState extends State<NestedContainerWidget> {
PageController _pageController;
ScrollController _listScrollController;
ScrollController _activeScrollController;
Drag _drag;
@override
void initState() {
super.initState();
_pageController = PageController();
_listScrollController = ScrollController();
}
@override
void dispose() {
_pageController.dispose();
_listScrollController.dispose();
super.dispose();
}
void _handleDragStart(DragStartDetails details) {
if (_listScrollController.hasClients &&
_listScrollController.position.context.storageContext != null) {
final RenderBox renderBox =
_listScrollController.position.context.storageContext.findRenderObject();
if (renderBox.paintBounds
.shift(renderBox.localToGlobal(Offset.zero))
.contains(details.globalPosition)) {
_activeScrollController = _listScrollController;
_drag = _activeScrollController.position.drag(details,_disposeDrag);
return;
}
}
_activeScrollController = _pageController;
_drag = _pageController.position.drag(details,_disposeDrag);
}
void _handleDragUpdate(DragUpdateDetails details) {
if (_activeScrollController == _listScrollController &&
details.primaryDelta < 0 &&
_activeScrollController.position.pixels ==
_activeScrollController.position.maxScrollExtent) {
_activeScrollController = _pageController;
_drag?.cancel();
_drag = _pageController.position.drag(
DragStartDetails(
globalPosition: details.globalPosition,localPosition: details.localPosition),_disposeDrag);
}
_drag?.update(details);
}
void _handleDragEnd(DragEndDetails details) {
_drag?.end(details);
}
void _handleDragCancel() {
_drag?.cancel();
}
void _disposeDrag() {
_drag = null;
}
@override
Widget build(BuildContext context) {
return RawGestureDetector(
gestures: <Type,GestureRecognizerFactory>{
VerticalDragGestureRecognizer:
GestureRecognizerFactoryWithHandlers<VerticalDragGestureRecognizer>(
() => VerticalDragGestureRecognizer(),(VerticalDragGestureRecognizer instance) {
instance
..onStart = _handleDragStart
..onUpdate = _handleDragUpdate
..onEnd = _handleDragEnd
..onCancel = _handleDragCancel;
})
},behavior: HitTestBehavior.opaque,child: PageView(
controller: _pageController,scrollDirection: Axis.vertical,physics: const NeverScrollableScrollPhysics(),children: [
Center(child: Text('Page 1')),ListView(
controller: _listScrollController,children: List.generate(
20,(int index) {
return ListTile(title: Text('Item $index'));
},),],);
}
}
请查看_handleDragStart
和_handleDragUpdate
中的逻辑,这些逻辑根据ListView
小部件的状态及其滚动状态确定应滚动的控制器。
我写了一篇有关此问题的详细文章,您可以在这里进行检查-https://medium.com/@Mak95/nested-scrolling-listview-inside-pageview-in-flutter-a57b7a6241b1
该解决方案可以改进,因此非常欢迎输入。
,
我使用 this answer 帮助我解决了同样的问题。
基本上,您使用 OverscrollNotification
监听 NotificationListener
的可滚动子级,并使用其控制器滚动父级。
代码:
final pageCntrler = PageController();
_scrollDown() async {
await pageCntrler.nextPage(
duration: scrollDuration,curve: scrollCurve,);
}
_scrollUp() async {
await pageCntrler.previousPage(
duration: scrollDuration,);
}
@override
Widget build(BuildContext context) {
return PageView(
controller: pageCntrler,physics: NeverScrollableScrollPhysics(),children: [
NotificationListener(
onNotification: (notification) {
if (notification is OverscrollNotification) {
if (notification.overscroll > 0) {
_scrollDown();
} else {
_scrollUp();
}
}
},child: SingleChildScrollView(),)
],);
}
本文链接:https://www.f2er.com/2982484.html