Flutter高级列表视图插件advanced_list_view的使用

Flutter 高级列表视图插件 advanced_list_view 的使用

特性

  • Flutter 列表视图
  • 分页选项(无限滚动)
  • 使用泛型类型检测视图模型
  • 刷新选项
  • 获取数据时错误处理
  • 当列表为空时显示空视图
  • 获取数据时显示加载视图
  • 简单易用
  • 使您的代码清晰且可读

开始使用

导入:

import 'package:advanced_list_view/advanced_list_view.dart';

使用示例

定义您的列表视图(PersonViewModel 是将在 itemBuilder 中返回给您的模型,并且您可以使用当前项值):

AdvancedListView<PersonViewModel>(
  items: listItems,
  canRefresh: true,
  showLoadingWidget: showLoadingWidget,
  showErrorWidget: showErrorWidget,
  shrinkWrap: true,
  showEmptyWidget: showEmptyWidget,
  onRefresh: _onRefresh,
  onLoadMoreData: _onLoadMoreData,
  hasMoreData: _hasMoreData,
  itemBuilder: 
    (final BuildContext context, final int index, final item) => 
    ListTile(
      title: Text(item.name),
    ),
),

用户滚动到列表末尾时调用的加载更多数据函数,偏移量将增加:

Future<void> _onLoadMoreData() async {
  setState(() {
    showErrorWidget = false;
    showEmptyWidget = false;
    showLoadingWidget = true;
  });
  final response = await Dio()
      .get('https://retoolapi.dev/cXYQ5x/data?_page=$offset&_limit=$limit');

  if (offset == 1) {
    listItems.clear();
  }

  List<PersonViewModel> receivedItems = [];

  receivedItems = (response.data as List)
      .map(
        (final e) => PersonViewModel.fromJson(e as Map<String, dynamic>),
  )
      .toList();

  listItems.addAll(receivedItems);

  setState(() {
    showLoadingWidget = false;
  });
  if (receivedItems.length < limit) {
    _hasMoreData = false;
  }
  offset++;
}    

定义刷新函数,当用户拉动列表或点击重试小部件时将被调用:

Future<void> _onRefresh() async {
  listItems.clear();
  offset = 1;
  setState(() {
    showLoadingWidget = true;
    showErrorWidget = false;
    showEmptyWidget = false;
  });
  _onLoadMoreData();
}

其他信息

有关更多信息,请查看 GitHub 仓库:https://github.com/aminJamali/advanced-list-view.git

完整示例代码

import 'dart:io';

import 'package:advanced_list_view/advanced_list_view.dart';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'person_view_model.dart';

void main() {
  HttpOverrides.global = MyHttpOverrides();
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Advanced List View',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Advanced List View Demo'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  [@override](/user/override)
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  bool _hasMoreData = true;
  int offset = 1;
  final int limit = 10;
  bool showErrorWidget = false,
      showEmptyWidget = false,
      showLoadingWidget = true;

  final List<PersonViewModel> listItems = [];

  Future<void> _onRefresh() async {
    listItems.clear();
    offset = 1;
    setState(() {
      showLoadingWidget = true;
      showErrorWidget = false;
      showEmptyWidget = false;
    });
    _onLoadMoreData();
  }

  Future<void> _onLoadMoreData() async {
    setState(() {
      showErrorWidget = false;
      showEmptyWidget = false;
      showLoadingWidget = true;
    });

    final response = await Dio()
        .get('https://retoolapi.dev/cXYQ5x/data?_page=$offset&_limit=$limit');

    if (offset == 1) {
      listItems.clear();
    }

    List<PersonViewModel> receivedItems = [];

    receivedItems = (response.data as List)
        .map(
          (final e) => PersonViewModel.fromJson(e as Map<String, dynamic>),
        )
        .toList();

    listItems.addAll(receivedItems);

    setState(() {
      showLoadingWidget = false;
    });
    if (receivedItems.length < limit) {
      _hasMoreData = false;
    }
    offset++;
  }

  [@override](/user/override)
  void initState() {
    _onLoadMoreData();
    super.initState();
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      bottomNavigationBar: _bottomNavBar(),
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: AdvancedListView<PersonViewModel>(
        items: listItems,
        canRefresh: true,
        showLoadingWidget: showLoadingWidget,
        showErrorWidget: showErrorWidget,
        shrinkWrap: true,
        showEmptyWidget: showEmptyWidget,
        onRefresh: _onRefresh,
        onLoadMoreData: _onLoadMoreData,
        hasMoreData: _hasMoreData,
        itemBuilder: 
            (final BuildContext context, final int index, final item) => 
                ListTile(
          title: Text(item.name),
        ),
      ),
    );
  }

  Widget _bottomNavBar() {
    return Container(
      decoration: const BoxDecoration(
        color: Colors.green,
      ),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: [
          _errorButton(),
          _emptyButton(),
        ],
      ),
    );
  }

  Widget _emptyButton() {
    return ElevatedButton(
      onPressed: () {
        setState(() {
          showEmptyWidget = true;
        });
      },
      child: const Text('显示空视图'),
    );
  }

  Widget _errorButton() {
    return ElevatedButton(
      onPressed: () {
        setState(() {
          showErrorWidget = true;
        });
      },
      child: const Text('显示错误视图'),
    );
  }
}

class MyHttpOverrides extends HttpOverrides {
  [@override](/user/override)
  HttpClient createHttpClient(SecurityContext? context) {
    return super.createHttpClient(context)
      ..badCertificateCallback =
          (X509Certificate cert, String host, int port) => true;
  }
}

更多关于Flutter高级列表视图插件advanced_list_view的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter高级列表视图插件advanced_list_view的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


advanced_list_view 是一个 Flutter 插件,它提供了比标准 ListView 更高级的功能,例如支持分页加载、下拉刷新、上拉加载更多等。这个插件非常适合用于需要处理大量数据或需要分页加载的场景。

安装

首先,你需要在 pubspec.yaml 文件中添加 advanced_list_view 的依赖:

dependencies:
  flutter:
    sdk: flutter
  advanced_list_view: ^0.0.1  # 请查看最新版本

然后运行 flutter pub get 来安装依赖。

基本使用

1. 导入包

import 'package:advanced_list_view/advanced_list_view.dart';

2. 创建 AdvancedListView

你可以使用 AdvancedListView 来创建一个带有分页加载功能的列表。以下是一个简单的示例:

class MyListPage extends StatefulWidget {
  @override
  _MyListPageState createState() => _MyListPageState();
}

class _MyListPageState extends State<MyListPage> {
  List<String> items = [];
  bool isLoading = false;
  bool hasMore = true;
  int page = 1;

  Future<void> _loadMore() async {
    if (isLoading || !hasMore) return;

    setState(() {
      isLoading = true;
    });

    // 模拟网络请求
    await Future.delayed(Duration(seconds: 2));

    List<String> newItems = List.generate(20, (index) => "Item ${items.length + index + 1}");

    setState(() {
      items.addAll(newItems);
      isLoading = false;
      hasMore = newItems.length == 20; // 假设每次加载20条数据,如果不到20条,说明没有更多数据了
      page++;
    });
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Advanced ListView Example'),
      ),
      body: AdvancedListView(
        itemCount: items.length + 1, // +1 是为了显示加载更多的指示器
        itemBuilder: (context, index) {
          if (index < items.length) {
            return ListTile(
              title: Text(items[index]),
            );
          } else {
            return _buildLoadMoreIndicator();
          }
        },
        onLoadMore: _loadMore,
        hasMore: hasMore,
      ),
    );
  }

  Widget _buildLoadMoreIndicator() {
    return Center(
      child: Padding(
        padding: EdgeInsets.all(8.0),
        child: isLoading ? CircularProgressIndicator() : Text('No more items'),
      ),
    );
  }
}

3. 下拉刷新

AdvancedListView 也支持下拉刷新功能。你可以通过 onRefresh 属性来指定刷新操作:

AdvancedListView(
  itemCount: items.length + 1,
  itemBuilder: (context, index) {
    if (index < items.length) {
      return ListTile(
        title: Text(items[index]),
      );
    } else {
      return _buildLoadMoreIndicator();
    }
  },
  onLoadMore: _loadMore,
  onRefresh: _refresh,
  hasMore: hasMore,
)

Future<void> _refresh() async {
  setState(() {
    items.clear();
    page = 1;
    hasMore = true;
  });

  await _loadMore();
}
回到顶部