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

js4nwp54  于 2023-07-31  发布在  Flutter
关注(0)|答案(9)|浏览(203)

我正在使用ListView小部件以列表形式显示项目。在一个窗口三,项目查看必须将中间的项目放置在中间.
那么,如何在滚动停止时检测ListView的位置?
如何检测ListView滚动停止?

zaqlnxep

zaqlnxep1#

我使用了 NotificationListener,这是一个小部件,用于侦听树中冒泡的通知。然后使用 ScrollEndNotification,表示滚动已停止。
对于滚动位置,我使用_scrollController,类型为 ScrollController

NotificationListener(
  child: ListView(
    controller: _scrollController,
    children: ...
  ),
  onNotification: (t) {
    if (t is ScrollEndNotification) {
      print(_scrollController.position.pixels);
    }
    //How many pixels scrolled from pervious frame
    print(t.scrollDelta);

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

字符串

ffvjumwh

ffvjumwh2#

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

字符串

yqlxgs2m

yqlxgs2m3#

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

字符串

hgtggwj0

hgtggwj04#

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

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

字符串


的数据

kjthegm6

kjthegm65#

如果你想检测你的ListView的滚动位置,你可以简单地使用它;
Scrollable.of(context).position.pixels

vdzxcuhz

vdzxcuhz6#

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

n53p2ov0

n53p2ov07#

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

字符串

fnx2tebb

fnx2tebb8#

我会说你可以很容易地检测滚动位置

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

yzuktlbb

yzuktlbb9#

使用此代码
类NotificationListenerListviewscroolller扩展StatelessWidget { NotificationListenerListviewscroolller({super.key});
int n = int n();
@override Widget build(BuildContext context){ final title = 'Grid List'; return Scaffold(appBar:AppBar(标题:文本(标题),),

body: NotificationListener<ScrollNotification>(
    onNotification: (scrollNotification) {
      print('inside the onNotification');
      if (_scrollController.position.userScrollDirection ==
          ScrollDirection.reverse) {
        print('scrolled down');
        //the setState function
      } else if (_scrollController.position.userScrollDirection ==
          ScrollDirection.forward) {
        print('scrolled up');
        //setState function
      }
      return true;
    },
    child: ListView(
      controller: _scrollController,
      // This next line does the trick.
      scrollDirection: Axis.vertical,
      children: <Widget>[
        Container(
          height: 200.0,
          color: Colors.red,
        ),
        Container(
          height: 160.0,
          color: Colors.blue,
        ),
        Container(
          height: 160.0,
          color: Colors.green,
        ),
        Container(
          height: 160.0,
          color: Colors.yellow,
        ),
        Container(
          height: 160.0,
          color: Colors.orange,
        ),
        Container(
          height: 200.0,
          color: Colors.red,
        ),
        Container(
          height: 160.0,
          color: Colors.blue,
        ),
        Container(
          height: 160.0,
          color: Colors.green,
        ),
        Container(
          height: 160.0,
          color: Colors.yellow,
        ),
        Container(
          height: 160.0,
          color: Colors.orange,
        ),
      ],
    ),
  ), // This trailing comma makes auto-formatting nicer for build methods.
);

字符串
{\fnSimHei\bord1\shad1\pos(200,288)}

相关问题