繁体   English   中英

Flutter中如何检测ListView的滚动位置

[英]How to detect scroll position of ListView in Flutter

我正在使用ListView小部件将项目显示为列表。 在窗口三中,查看的项目必须将中间的项目放在中间。

那么如何在滚动停止时检测ListView的位置呢?

如何检测 ListView 滚动停止?

我使用了NotificationListener ,它是一个小部件,用于侦听在树上冒泡的通知。 然后使用ScrollEndNotification ,它表示滚动已停止。

对于滚动位置,我使用_scrollController类型为ScrollController

NotificationListener(
  child: ListView(
    controller: _scrollController,
    children: ...
  ),
  onNotification: (t) {
    if (t is ScrollEndNotification) {
      print(_scrollController.position.pixels);
    }
  },
),

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);
  },
),

您还可以通过以下步骤实现此功能

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'),
      );
    },
  )),
);
}
}

在此处输入图像描述

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;
  },
),

如果你想检测ListView的滚动位置,你可以简单地使用它;

Scrollable.of(context).position.pixels

除了@seddiq-sorush 回答,你可以将当前位置与_scrollController.position.maxScrollExtent进行比较,看看列表是否在底部

我会说您可以通过以下方式轻松检测滚动位置

@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,
  ),

https://coflutter.com/flutter-check-if-the-listview-reaches-the-top-or-the-bottom/来源

如果有人想检测列表视图的底部,那么使用这种方式

NotificationListener<ScrollNotification>(
 onNotification: (ScrollNotification notification) {
 if (notification.metrics.atEdge) {
    if (notification.metrics.pixels == 0) {
      print('At top');
    } else {
      print('At bottom');
    }
}
return true;
},
child: ListView.builder(itemBuilder: (BuildContext context) {
  return YourItemWidget;
})
)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM