패키지, 저장소 및 앱 카테고리 검색

패키지 상세v7.1.0

loading_more_list

ListView, GridView, WaterfallFlow 및 Slivers를 지원하는 더 보기 목록입니다.

AndroidiOSWebmacOSWindowsLinux
30일 다운로드
3.7천
좋아요
183
Pub 점수
150

패키지 설치

flutter pub add loading_more_list

패키지 개요

공개 정보를 바탕으로 생성한 선택 가이드입니다.

ListView, GridView, WaterfallFlow 및 Sliver 위젯을 포함한 다양한 리스트 유형에 대해 무한 스크롤과 로딩 인디케이터를 활성화하는 Flutter 패키지입니다. 리스트의 끝부분에 가까워질 때 자동으로 스크롤 위치를 감지하고 로드 이벤트를 트리거함으로써 페이징을 간소화합니다. 데이터가 많은 앱에서 원활한 사용자 경험을 위해 설계되었으며, 여러 플랫폼을 지원하고 기존의 스크롤 가능한 컴포넌트와 매끄럽게 통합됩니다.

사용 사례

  • 무한 스크롤 피드
  • 지연 로딩 그리드
  • 동적 콘텐츠 페이지네이션
  • 대규모 데이터 세트를 포함한 앱
  • 사용자 정의 가능한 로딩 인디케이터

주요 기능

  • ListView, GridView, WaterfallFlow 및 Slivers를 지원합니다
  • 목록 끝 자동 감지
  • 사용자 정의 가능한 로딩 상태
  • 크로스 플랫폼 호환성
  • 기존 스크롤 뷰와의 간편한 통합

적합한 대상

  • 긴 목록을 가진 앱
  • 콘텐츠 중심의 UI
  • 페이지네이션 구현
  • 재사용 가능한 스크롤 로직을 찾는 개발자
  • 부드러운 로딩 전환을 필요로 하는 프로젝트

고려 사항

  • 비동기 데이터 가져오기에 적절한 처리가 필요합니다
  • 복잡한 시나리오를 위한 사용자 정의 로딩 로직이 필요할 수 있습니다
  • 정적 또는 작은 데이터 세트에 적합하지 않습니다
  • 성능은 항목 렌더링 효율에 따라 달라집니다
  • 새로 고치는 동안 주의 깊은 상태 관리가 필요합니다

원본 README

연결된 소스 저장소의 README 원문 스냅샷입니다. 최신 내용은 저장소에서 확인하세요.

loading_more_list

A loading more list which supports ListView,GridView,WaterfallFlow and Slivers.

pub package GitHub stars GitHub forks GitHub license GitHub issues FlutterCandies QQ 群

Language: English | 中文简体

Web demo for LoadingMoreList

Use

  • add library to your pubspec.yaml

dependencies:
  loading_more_list: any

  • import library in dart file

  import 'package:loading_more_list/loading_more_list.dart';

Prepare Data Collection

LoadingMoreBase is data collection for loading more. override loadData method to load your data. set hasMore to false when it has no more data.

class TuChongRepository extends LoadingMoreBase<TuChongItem> {
  int pageindex = 1;
  bool _hasMore = true;
  bool forceRefresh = false;
  @override
  bool get hasMore => (_hasMore && length < 30) || forceRefresh;

  @override
  Future<bool> refresh([bool clearBeforeRequest = false]) async {
    _hasMore = true;
    pageindex = 1;
    //force to refresh list when you don't want clear list before request
    //for the case, if your list already has 20 items.
    forceRefresh = !clearBeforeRequest;
    var result = await super.refresh(clearBeforeRequest);
    forceRefresh = false;
    return result;
  }

  @override
  Future<bool> loadData([bool isloadMoreAction = false]) async {
    String url = "";
    if (this.length == 0) {
      url = "https://api.tuchong.com/feed-app";
    } else {
      int lastPostId = this[this.length - 1].postId;
      url =
          "https://api.tuchong.com/feed-app?post_id=$lastPostId&page=$pageindex&type=loadmore";
    }
    bool isSuccess = false;
    try {
      //to show loading more clearly, in your app,remove this
      await Future.delayed(Duration(milliseconds: 500));

      var result = await HttpClientHelper.get(url);

      var source = TuChongSource.fromJson(json.decode(result.body));
      if (pageindex == 1) {
        this.clear();
      }
      for (var item in source.feedList) {
        if (item.hasImage && !this.contains(item) && hasMore) this.add(item);
      }

      _hasMore = source.feedList.length != 0;
      pageindex++;
      isSuccess = true;
    } catch (exception, stack) {
      isSuccess = false;
      print(exception);
      print(stack);
    }
    return isSuccess;
  }
}

Argument

almost of arguments are the same as official.

following arguments are made for loading more.

ListConfig and SliverListConfig

argument description default
itemBuilder The item builder of list. required
sourceList The source list of data which extends LoadingMoreBase. required
showGlowLeading Whether to show the overscroll glow on the side with negative scroll offsets. 0.0
showGlowTrailing Whether to show the overscroll glow on the side with positive scroll offsets. -
lastChildLayoutType Layout type of last child(loadmore/no more item). LastChildLayoutType.foot
extendedListDelegate The delegate for WaterfallFlow or ExtendedList. -
gridDelegate The delegate for GridView. -
indicatorBuilder widget builder for different loading state. IndicatorWidget
padding The amount of space by which to inset the child sliver for SliverListConfig -
childCountBuilder The builder to get child count, the input is sourceList.length -

Widget

LoadingMoreList

argument description default
listConfig ListConfig required
onScrollNotification Called when a ScrollNotification of the appropriate type arrives at this location in the tree. -

LoadingMoreSliverList

argument description default
sliverListConfig SliverListConfig required

LoadingMoreCustomScrollView

argument description default
onScrollNotification Called when a ScrollNotification of the appropriate type arrives at this location in the tree. -

ListView

            LoadingMoreList(
              ListConfig<TuChongItem>(
                itemBuilder: ItemBuilder.itemBuilder,
                sourceList: listSourceRepository,
                padding: EdgeInsets.all(0.0),
              ),
            ),

GridView

define GridView with gridDelegate argument.

            LoadingMoreList(
              ListConfig<TuChongItem>(
                itemBuilder: ItemBuilder.itemBuilder,
                sourceList: listSourceRepository,
                padding: EdgeInsets.all(0.0),
                gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                  crossAxisCount: 2,
                  crossAxisSpacing: 3.0,
                  mainAxisSpacing: 3.0,
                ),
              ),
            ),

WaterfallFlow

define WaterfallFlow with waterfallFlowDelegate argument.

            LoadingMoreList(
              ListConfig<TuChongItem>(
                extendedListDelegate: SliverWaterfallFlowDelegateWithFixedCrossAxisCount(
                  crossAxisCount: 2,
                  crossAxisSpacing: 5,
                  mainAxisSpacing: 5,
                ),
                itemBuilder: _buildItem,
                sourceList: listSourceRepository,
                padding: EdgeInsets.all(5.0),
              ),
            ),

Sliver/CustomScrollView

following codes are show how to build loading more list within CustomScrollView.

      LoadingMoreCustomScrollView(
        slivers: <Widget>[
          SliverAppBar(
            pinned: true,
            title: Text("MultipleSliverDemo"),
          ),
          ///SliverList
          LoadingMoreSliverList(SliverListConfig<TuChongItem>(
            itemBuilder: ItemBuilder.itemBuilder,
            sourceList: listSourceRepository,
          )),
          SliverToBoxAdapter(
            child: Container(
              alignment: Alignment.center,
              child: Text("Next list"),
              color: Colors.blue,
              height: 100.0,
            ),
          ),
          ///SliverGrid
          LoadingMoreSliverList(
            SliverListConfig<TuChongItem>(
              itemBuilder: ItemBuilder.itemBuilder,
              sourceList: listSourceRepository1,
              gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                crossAxisCount: 2,
                crossAxisSpacing: 3.0,
                mainAxisSpacing: 3.0,
              ),
            ),
          ),
          SliverPersistentHeader(
            delegate: CommonExtentSliverPersistentHeaderDelegate(
                Container(
                  alignment: Alignment.center,
                  child: Text("Pinned Content"),
                  color: Colors.red,
                ),
                100.0),
            pinned: true,
          ),
          ///SliverWaterfallFlow
          LoadingMoreSliverList(
            SliverListConfig<TuChongItem>(
              itemBuilder: buildWaterfallFlowItem,
              sourceList: listSourceRepository2,
              padding: EdgeInsets.symmetric(horizontal: 5.0),
              extendedListDelegate: SliverWaterfallFlowDelegateWithFixedCrossAxisCount(
                crossAxisCount: 2,
                crossAxisSpacing: 5,
                mainAxisSpacing: 5,
              ),
            ),
          ),
        ],
      ),

IndicatorStatus

define loading status with indicatorBuilder argument.

        enum IndicatorStatus {
          None,
          LoadingMoreBusying,
          FullScreenBusying,
          Error,
          FullScreenError,
          NoMoreLoad,
          Empty
        }
      LoadingMoreList(
        ListConfig<TuChongItem>(
          itemBuilder: ItemBuilder.itemBuilder,
          sourceList: listSourceRepository,
          indicatorBuilder: _buildIndicator,
          padding: EdgeInsets.all(0.0),
        ),
      ),

  //you can use IndicatorWidget or build yourself widget
  //in this demo, we define all status.
  Widget _buildIndicator(BuildContext context, IndicatorStatus status) {
    //if your list is sliver list ,you should build sliver indicator for it
    //isSliver=true, when use it in sliver list
    bool isSliver = false;

    Widget widget;
    switch (status) {
      case IndicatorStatus.None:
        widget = Container(height: 0.0);
        break;
      case IndicatorStatus.LoadingMoreBusying:
        widget = Row(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: <Widget>[
            Container(
              margin: EdgeInsets.only(right: 5.0),
              height: 15.0,
              width: 15.0,
              child: getIndicator(context),
            ),
            Text("正在加载...不要着急")
          ],
        );
        widget = _setbackground(false, widget, 35.0);
        break;
      case IndicatorStatus.FullScreenBusying:
        widget = Row(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: <Widget>[
            Container(
              margin: EdgeInsets.only(right: 0.0),
              height: 30.0,
              width: 30.0,
              child: getIndicator(context),
            ),
            Text("正在加载...不要着急")
          ],
        );
        widget = _setbackground(true, widget, double.infinity);
        if (isSliver) {
          widget = SliverFillRemaining(
            child: widget,
          );
        } else {
          widget = CustomScrollView(
            slivers: <Widget>[
              SliverFillRemaining(
                child: widget,
              )
            ],
          );
        }
        break;
      case IndicatorStatus.Error:
        widget = Text(
          "好像出现了问题呢?",
        );
        widget = _setbackground(false, widget, 35.0);

        widget = GestureDetector(
          onTap: () {
            listSourceRepository.errorRefresh();
          },
          child: widget,
        );

        break;
      case IndicatorStatus.FullScreenError:
        widget = Text(
          "好像出现了问题呢?",
        );
        widget = _setbackground(true, widget, double.infinity);
        widget = GestureDetector(
          onTap: () {
            listSourceRepository.errorRefresh();
          },
          child: widget,
        );
        if (isSliver) {
          widget = SliverFillRemaining(
            child: widget,
          );
        } else {
          widget = CustomScrollView(
            slivers: <Widget>[
              SliverFillRemaining(
                child: widget,
              )
            ],
          );
        }
        break;
      case IndicatorStatus.NoMoreLoad:
        widget = Text("没有更多的了。。不要拖了");
        widget = _setbackground(false, widget, 35.0);
        break;
      case IndicatorStatus.Empty:
        widget = EmptyWidget(
          "这里是空气!",
        );
        widget = _setbackground(true, widget, double.infinity);
        if (isSliver) {
          widget = SliverToBoxAdapter(
            child: widget,
          );
        } else {
          widget = CustomScrollView(
            slivers: <Widget>[
              SliverFillRemaining(
                child: widget,
              )
            ],
          );
        }
        break;
    }
    return widget;
  }

CollectGarbage

track the indexes are collect, you can collect garbage at that monment(for example Image cache)

more detail

        LoadingMoreList(
          ListConfig<TuChongItem>(
            extendedListDelegate: ExtendedListDelegate(
              collectGarbage: (List<int> indexes) {
                ///collectGarbage
              },
            ),
          ),
        ),

ViewportBuilder

track the indexes go into the viewport, it's not include cache extent.

        LoadingMoreList(
          ListConfig<TuChongItem>(
            extendedListDelegate: ExtendedListDelegate(
              viewportBuilder: (int firstIndex, int lastIndex) {
                print('viewport : [$firstIndex,$lastIndex]');
              },
            ),
          ),
        ),

LastChildLayoutType

build lastChild as special child in the case that it is loadmore/no more item.

        enum LastChildLayoutType {
        /// as default child
        none,

        /// follow max child trailing layout offset and layout with full cross axis extent
        /// last child as loadmore item/no more item in [ExtendedGridView] and [WaterfallFlow]
        /// with full cross axis extend
        fullCrossAxisExtent,

        /// as foot at trailing and layout with full cross axis extend
        /// show no more item at trailing when children are not full of viewport
        /// if children is full of viewport, it's the same as fullCrossAxisExtent
        foot,
        }

CloseToTrailing

when reverse property of List is true, layout is as following. it likes chat list, and new session will insert to zero index. but it's not right when items are not full of viewport.

     trailing
-----------------
|               |
|               |
|     item2     |
|     item1     |
|     item0     |
-----------------
     leading

to solve it, you could set closeToTrailing to true, layout is as following. support [ExtendedGridView],[ExtendedList],[WaterfallFlow]. and it also works when reverse is flase, layout will close to trailing.

     trailing
-----------------
|     item2     |
|     item1     |
|     item0     |
|               |
|               |
-----------------
     leading
      LoadingMoreList(
        ListConfig<TuChongItem>(
          extendedListDelegate: ExtendedListDelegate(
            closeToTrailing: true
          ),
        ),
      ),

카테고리

의존성

의존성 목록 4 개

소스 저장소

이 패키지를 사용하는 프로젝트