首页 > 解决方案 > 当我们接近底部[FLUTTER]时如何实现无限滚动?

问题描述

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

  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 次......我怎样才能正确地做到这一点?

标签: flutterscrolllazy-loadinginfinitebottom

解决方案


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

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

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

            ],
          ),
        ],
      )
    );

推荐阅读