Flutter中如何检测ListView的滚动位置
Posted
技术标签:
【中文标题】Flutter中如何检测ListView的滚动位置【英文标题】:How to detect scroll position of ListView in Flutter 【发布时间】:2019-06-01 14:01:53 【问题描述】:我正在使用ListView
小部件将项目显示为列表。在窗口三中,查看的项目必须将中间的项目放在中间。
那么如何在滚动停止时检测ListView
的位置?
如何检测 ListView 滚动停止?
【问题讨论】:
【参考方案1】:我使用了 NotificationListener
,它是一个小部件,用于侦听在树上冒泡的通知。然后使用ScrollEndNotification
,表示滚动已停止。
对于滚动位置,我使用了_scrollController
,该类型是ScrollController
。
NotificationListener(
child: ListView(
controller: _scrollController,
children: ...
),
onNotification: (t)
if (t is ScrollEndNotification)
print(_scrollController.position.pixels);
,
),
【讨论】:
您将这些代码放在哪里,在 ListView (ui) 中还是在 bloc 中? 孩子:新的 NotificationListener( 对于 2021 年的用户,有一种更短的方法可以做到这一点(见我的回答):)【参考方案2】:我会说您可以通过
轻松检测滚动位置@override
void initState()
super.initState();
_scrollController = ScrollController();
_scrollController.addListener(()
var _currectScrollPosition = _scrollController.position.pixels;//this is the line
);
但是如果你要在 addListener() 中调用 setState ;没关系,但这会导致重建整个构建(上下文)。对于动画来说,这不是一个好习惯。
我建议将您的滚动小部件分离成一个单独的 StatefulWidget ,然后通过调用获取该小部件的状态
_yourScrollableWidgetKey.currentState?.controller.addListener(()
//code.......
setState(() );
);
注意:设置一个 GlobalKey,并分配给您的 StatFulWidget。
final _yourScrollableWidgetKey = GlobalKey<_YourScrollAbleWidget>();
StackedPositionedAnimated(
key: _yourScrollableWidgetKey,
),
【讨论】:
【参考方案3】:NotificationListener
现在接受一个使代码更短的类型参数:)
NotificationListener<ScrollEndNotification>(
child: ListView(
controller: _scrollController,
children: ...
),
onNotification: (notification)
print(_scrollController.position.pixels);
// Return true to cancel the notification bubbling. Return false (or null) to
// allow the notification to continue to be dispatched to further ancestors.
return true;
,
),
【讨论】:
有了NotificationListener<ScrollEndNotification>
,我相信除了打印像素之外,您不再需要_scrollController
。【参考方案4】:
除了@seddiq-sorush的回答,你可以将当前位置与_scrollController.position.maxScrollExtent
比较,看看列表是否在底部
【讨论】:
【参考方案5】:majidfathi69 的回答很好,但您不需要在列表中添加控制器:
(如果您只想在滚动结束时收到通知,请将 ScrollUpdateNotification
更改为 ScrollEndNotification
。)
NotificationListener<ScrollUpdateNotification>(
child: ListView(
children: ...
),
onNotification: (notification)
//How many pixels scrolled from pervious frame
print(notification.scrollDelta);
//List scroll position
print(notification.metrics.pixels);
,
),
【讨论】:
【参考方案6】:您也可以通过以下步骤实现此功能
import 'package:flutter/material.dart';
class YourPage extends StatefulWidget
YourPage(Key key) : super(key: key);
@override
_YourPageState createState() => _YourPageState();
class _YourPageState extends State<YourPage>
ScrollController _scrollController;
double _scrollPosition;
_scrollListener()
setState(()
_scrollPosition = _scrollController.position.pixels;
);
@override
void initState()
_scrollController = ScrollController();
_scrollController.addListener(_scrollListener);
super.initState();
@override
Widget build(BuildContext context)
return Scaffold(
appBar: AppBar(
automaticallyImplyLeading: false,
title: Text('Position $_scrollPosition pixels'),
),
body: Container(
child: ListView.builder(
controller: _scrollController,
itemCount: 200,
itemBuilder: (context, index)
return ListTile(
leading: Icon(Icons.mood),
title: Text('Item: $index'),
);
,
)),
);
【讨论】:
【参考方案7】:如果你想检测你的ListView
的滚动位置,你可以简单地使用这个;
Scrollable.of(context).position.pixels
【讨论】:
如何检测 ListView 滚动停止?以上是关于Flutter中如何检测ListView的滚动位置的主要内容,如果未能解决你的问题,请参考以下文章
在 Flutter 中使用 InheritedWidget 时 ListView 失去滚动位置
Flutter - ListView.builder:初始滚动位置
如何使用 Flutter 从 Firestore 中的 ListView 获得无限滚动
25.Flutter的ListView监听滚动事件之ScrollController