【问题标题】:How can I implement infinite scroll when we get close to bottom[FLUTTER]?当我们接近底部[FLUTTER]时如何实现无限滚动?
【发布时间】:2021-02-02 19:05:52
【问题描述】:

当我使用以下代码时,当我到达列表视图的底部时,我可以获取新数据

  controller.addListener(() {
    if(controller.position.pixels==controller.position.maxScrollExtent){
      postController.fetchNewPosts(postController.postList.last.timeupdated);
    }
  });

但我想获取它们不是在我到达底部时,而是在我接近它时,这样用户就不会在到达底部时等待。

child: Obx(() => NotificationListener<ScrollNotification>(
      onNotification: (ScrollNotification notification){
        if(notification.metrics.maxScrollExtent > notification.metrics.pixels &&
            notification.metrics.maxScrollExtent - notification.metrics.pixels <=
                60.0){
          print(postController.postList.last.post);
          postController.fetchNewPosts(postController.postList.last.timeupdated);
          print('DENEME');
        }
        return false;
      },
      child: ListView.builder(
          controller: controller,
          itemCount: postController.postList.length,
          itemBuilder: (context, index) {
            return Card(
              child: Row(

当我使用此代码时,它会在一秒钟内触发该函数 15 次... 我该如何正确地做到这一点?

【问题讨论】:

  • 你有解决办法吗?

标签: flutter scroll lazy-loading infinite bottom


【解决方案1】:

你不需要像这样的 NotificationListener,因为它在构建时一直在执行。

尝试添加一个 ScrollController

final ScrollController scrollController = ScrollController();

之后添加一个滚动监听方法

void _scrollListener() {
    if (scrollController.offset >= scrollController.position.maxScrollExtent &&
        !scrollController.position.outOfRange) {
       print(postController.postList.last.post);
      postController.fetchNewPosts(postController.postList.last.timeupdated);
      print('DENEME');
      }
    }
  }

并在 initState 中将此侦听器添加到滚动控制器

@override
  void initState() {
    scrollController.addListener(_scrollListener);
    super.initState();
  }

【讨论】:

  • 我很欣赏你的回答,但它没有做我想做的事。当我到达底部时它会获取新帖子,但我想在到达之前获取它们,但是当我接近时
  • 它工作正常,但我想在到达底部之前稍微获取数据
【解决方案2】:

改为:

  controller.addListener(() {
    if(controller.position.pixels==controller.position.maxScrollExtent-200){
      postController.fetchNewPosts(postController.postList.last.timeupdated);
    }
  });

200是到达底部之前的距离,设置任何你喜欢的值

【讨论】:

  • 感谢您的帮助,但它从来没有用过,我已经尝试过很多次了。当你滚动时,你跳过了那个像素,你永远不会触发那个像素中的函数,你只是跳过它
【解决方案3】:

我用https://pub.dev/packages/inview_notifier_list 这个库来实现。 在低层设备中,它可能会导致性能问题。比如卡顿、框架问题。

这里是例子。 希望对你有所帮助。

SafeArea(
      child: Stack(
        children: [
          InViewNotifierCustomScrollView(
            physics: Platform.isAndroid ? ClampingScrollPhysics() : RangeMaintainingScrollPhysics(),
            isInViewPortCondition: widget.inViewPortCondition ??
                    (double deltaTop, double deltaBottom, double vpHeight) {
                  return deltaTop < (0.7 * vpHeight) && deltaBottom > (0.7 * vpHeight);
                },
            endNotificationOffset: mw(500),
            onListEndReached: () async{
              if(_list1.length == _totCnt) {
                setState(() {
                  _noMoreItem = 'No more Models';
                });
              } else {
                if(_moreItems) {
                  setState(() {
                    _isLoad = true;
                    _moreItems = false;
                    _offset = _offset + 30;
                  });
                  bool _rrr = await getModelList($user.accessToken, $user.appInfo);
                  if(_rrr) {
                    setState(() {
                      _moreItems = true;
                    });
                  }
                } else {
                }
              }
            },
            controller: _bscrollController,
            slivers: [
              SliverAppBar(
                automaticallyImplyLeading: false,
                elevation: 0,
                brightness: Brightness.light,
                title: Text('Models', style: Ts.h15bb(),),
                actions: [
                  GestureDetector(
                      behavior: HitTestBehavior.translucent,
                      onTap: () {
                        Navigator.push(context,MaterialPageRoute(builder: (context) => SearchPage()));
                      },
                      child: Icon(Icons.search, size: mw(26),)),
                  SizedBox(width: mw(10),),
                  GestureDetector(
                      behavior: HitTestBehavior.translucent,
                      onTap: () {
                        Navigator.push(context,MaterialPageRoute(builder: (context) => CartPage()));
                      },
                      child:  Stack(
                        children: [
                          Padding(
                            padding: EdgeInsets.only(top: mw(13), right: mw(18)),
                            child: Image.asset('assets/pickling_cart.png', width: mw(18), height: mw(22),),
                          ),
                          $user.cartCnt == '0' ? Container():Positioned(
                              top: mw(9),
                              right: mw(10),
                              child: ClipRRect(
                                borderRadius: BorderRadius.all(Radius.circular(10)),
                                child: Container(
                                  height: mw(16),
                                  padding: EdgeInsets.only(left: mw(5), right: mw(5), bottom: mw(2)),
                                  color: Colors.black,
                                  child: Center(child: Text('${$user.cartCnt}', style: Ts.ctwb(),),),
                                ),
                              )
                          )
                        ],
                      )),
                ],
              ),

              _totCnt == 0 ?
              SliverToBoxAdapter(
                child: Padding(
                  padding: EdgeInsets.only(top:mw(50)),
                  child:
                  Center(
                      child: Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    crossAxisAlignment: CrossAxisAlignment.center,
                    children: [
                      Text('There are no models!', style: Ts.h3bb()),
                      SizedBox(height:mw(5)),
                      Text(':X', style: Ts.bd1gm(),),
                    ],
                  ))
                ),
              ):
              SliverPadding(
                padding: EdgeInsets.only(top: mw(2)),
                sliver: SliverList(
                  delegate: SliverChildBuilderDelegate(
                    (BuildContext context, int index) {
                      return Column(
                        children: [
                          ModelItem(imgURL,index,$user),
                          Divider(thickness: 1, color: Du.lightGrey(),)
                        ],
                      );
                    },
                      childCount: _list1.length
                  )
                )
              )

            ],
          ),
        ],
      )
    );

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-09-23
    • 1970-01-01
    • 2012-10-13
    • 1970-01-01
    • 2022-06-16
    • 1970-01-01
    • 2023-03-26
    相关资源
    最近更新 更多