简体   繁体   中英

How to detect scroll position of ListView in Flutter

I'm using ListView widget to show items as a list. In a window three, items viewing must the middle item place in the middle.

So how can I detect position of ListView when scrolling stop?

How to detect ListView Scrolling stopped?

I used NotificationListener that is a widget that listens for notifications bubbling up the tree. Then use ScrollEndNotification , which indicates that scrolling has stopped.

For scroll position I used _scrollController that type is ScrollController .

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

majidfathi69's answer is good, but you don't need to add a controller to the list: (Change ScrollUpdateNotification to ScrollEndNotification when you only want to be notified when scroll ends.)

NotificationListener<ScrollUpdateNotification>(
  child: ListView(
    children: ...
  ),
  onNotification: (notification) {
    //How many pixels scrolled from pervious frame
    print(notification.scrollDelta);

    //List scroll position
    print(notification.metrics.pixels);
  },
),

You can also achieve this functionality with the following steps

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

在此处输入图像描述

The NotificationListener now accepts a type argument which makes the code shorter :)

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进行比较,看看列表是否在底部

I would say You can easily detect Scroll Position by

@override
  void initState() {
    super.initState();

    _scrollController = ScrollController();
    _scrollController.addListener(() {
      var _currectScrollPosition = _scrollController.position.pixels;//this is the line
    });
  }

but If you are going to call setState in addListener() ; It is okay, but this will cause to rebuild your entire build(context). This is not a good practice for Animations specially.

What I would recommand is to seprate your scrolling widget into a seprate StatefulWidget , Then get the sate of that widget by calling

  _yourScrollableWidgetKey.currentState?.controller.addListener(() {
      //code.......
      setState(() {});
    });

Note: Set a GlobalKey, and assign to your StatFulWidget.

  final _yourScrollableWidgetKey = GlobalKey<_YourScrollAbleWidget>();
  StackedPositionedAnimated(
    key: _yourScrollableWidgetKey,
  ),

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

If some want to Detect the bottom of a listview then use this way

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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