Flutter无限滚动视图插件infinite_scroll_view的使用

发布于 1周前 作者 sinazl 来自 Flutter

Flutter无限滚动视图插件infinite_scroll_view的使用

Infinite Scoll View

<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12"> <rect x="1" y="1" width="10" height="10" fill="#007ACC"/> </svg> [pub package](https://pub.dartlang.org/packages/infinite_scroll_view) <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12"> <rect x="1" y="1" width="10" height="10" fill="#007ACC"/> </svg> [codecov](https://codecov.io/gh/infinite_scroll_view) <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12"> <rect x="1" y="1" width="10" height="10" fill="#007ACC"/> </svg> [Build Status](https://github.com/Jerinji2016/infinite_scroll_view/actions/workflows/flutter_tests.yaml)

一个用于实现无限滚动视图的Flutter库。

开始使用

在终端运行以下命令以安装包:

flutter pub add infinite_scroll_view

或者在 pubspec.yaml 文件中添加 infinite_scroll_view

dependencies:
  infinite_scroll_view: ^x.x.x

使用方法

使用 InfinitePageView

InfinitePageView 可以实现无限滚动效果。以下是基本用法:

InfinitePageView(
    onPageChanged: (index) {
        print('$index');
    },
    itemBuilder: (context, index) {
        return Text("Page $index");
    },
)

使用控制器控制 InfinitePageView

可以通过控制器来控制 InfinitePageView 的行为:

final InfinitePageController controller = InfinitePageController();

// ...

InfinitePageView(
    controller: controller,
    itemBuilder: (context, index) {
        return Text("Page $index");
    },
)

如何工作

InfinitePageView

InfinitePageView 通过创建一个包含两个页面的 PageView 来实现无限滚动效果。这两个页面实际上也是 PageView,并且在内部分别受到控制以达到所需的效果。

待办事项

  • 创建 InfiniteListView

限制

  • InfinitePageView 不支持 viewport fraction

完整示例代码

以下是完整的示例代码,展示如何使用 InfinitePageView 实现一个带有跳转功能的无限滚动视图。

import 'package:flutter/material.dart';
import 'package:infinite_scroll_view/infinite_scroll_view.dart';

import 'jump_to_page_panel.dart';
import 'primary_button.dart';

void main() {
  runApp(
    const MaterialApp(
      home: MyApp(),
      debugShowCheckedModeBanner: false,
    ),
  );
}

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

  [@override](/user/override)
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final InfinitePageController controller = InfinitePageController(
    keepPage: true,
    initialPage: 10,
  );

  final GlobalKey<JumpToPagePanelState> _jumpToPageKey = GlobalKey();

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

    controller.addListener(_listener);
  }

  void _listener() {
    debugPrint("_MyAppState._listener: page: ${controller.page}");
  }

  [@override](/user/override)
  void dispose() {
    super.dispose();
    controller
      ..removeListener(_listener)
      ..dispose();
  }

  void _onPageChanged(int index) => _jumpToPageKey.currentState?.pageChanged(index);

  void _changePage(bool isNext) => isNext
      ? controller.nextPage(
          duration: const Duration(milliseconds: 200),
          curve: Curves.ease,
        )
      : controller.previousPage(
          duration: const Duration(milliseconds: 200),
          curve: Curves.ease,
        );

  Future<void> _goToPage(int page, bool shouldAnimate) async {
    if (shouldAnimate) {
      return controller.animateToPage(
        page,
        duration: const Duration(seconds: 2),
        curve: Curves.ease,
      );
    }

    return controller.jumpToPage(page);
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        children: [
          InfinitePageView(
            pageSnapping: true,
            scrollDirection: Axis.vertical,
            controller: controller,
            onPageChanged: _onPageChanged,
            itemBuilder: (context, index) {
              return _Page(index: index);
            },
          ),
          Positioned(
            bottom: 24,
            right: 24,
            child: PrimaryButton(
              onTap: () => _changePage(true),
              text: "Next Page",
              borderRadius: 8.0,
              suffixIcon: Icons.navigate_next,
            ),
          ),
          Positioned(
            bottom: 24,
            left: 24,
            child: PrimaryButton(
              onTap: () => _changePage(false),
              text: "Prev Page",
              borderRadius: 8.0,
              prefixIcon: Icons.navigate_before,
            ),
          ),
          Positioned(
            bottom: 80.0,
            left: 0.0,
            right: 0.0,
            child: JumpToPagePanel(
              key: _jumpToPageKey,
              onPageIndexSelected: _goToPage,
            ),
          ),
        ],
      ),
    );
  }
}

class _Page extends StatelessWidget {
  final int index;

  const _Page({
    Key? key,
    required this.index,
  }) : super(key: key);

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Center(
      child: Text(
        "Page $index",
        textAlign: TextAlign.center,
        style: const TextStyle(
          color: Colors.orange,
          fontWeight: FontWeight.bold,
          fontSize: 18.0,
        ),
      ),
    );
  }
}

更多关于Flutter无限滚动视图插件infinite_scroll_view的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter无限滚动视图插件infinite_scroll_view的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何使用Flutter中的infinite_scroll_view插件来实现无限滚动视图的示例代码。请注意,infinite_scroll_view并不是Flutter官方插件,而是一个社区提供的插件,因此确保你已经将其添加到你的pubspec.yaml文件中。

首先,确保你的pubspec.yaml文件包含以下依赖项:

dependencies:
  flutter:
    sdk: flutter
  infinite_scroll_view: ^最新版本号 # 请替换为实际最新版本号

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

以下是一个简单的示例代码,展示如何使用infinite_scroll_view来实现无限滚动列表:

import 'package:flutter/material.dart';
import 'package:infinite_scroll_view/infinite_scroll_view.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Infinite Scroll View Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: InfiniteScrollPage(),
    );
  }
}

class InfiniteScrollPage extends StatefulWidget {
  @override
  _InfiniteScrollPageState createState() => _InfiniteScrollPageState();
}

class _InfiniteScrollPageState extends State<InfiniteScrollPage> {
  final List<String> items = List.generate(20, (index) => "Item $index");
  bool isLoading = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Infinite Scroll View Demo'),
      ),
      body: InfiniteScrollView.builder(
        itemCount: items.length + (isLoading ? 1 : 0), // 当加载时,额外添加一个占位符项
        itemBuilder: (context, index) {
          if (index >= items.length) {
            // 显示加载指示器
            return Center(
              child: CircularProgressIndicator(),
            );
          }
          return ListTile(
            title: Text(items[index]),
          );
        },
        onLoadMore: () async {
          setState(() {
            isLoading = true;
          });

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

          // 添加更多项目
          setState(() {
            int start = items.length;
            int end = start + 20;
            items.addAll(List.generate(20, (i) => "Item ${start + i}"));
            isLoading = false;
          });
        },
      ),
    );
  }
}

代码解释:

  1. 依赖项:确保在pubspec.yaml中添加了infinite_scroll_view依赖项。
  2. 主应用MyApp是应用的入口,设置了一个基本的Material应用,并将InfiniteScrollPage作为主页。
  3. 滚动页面InfiniteScrollPage是一个有状态的Widget,用于管理滚动列表的状态。
  4. 数据列表items列表存储了当前显示的项目。
  5. 加载状态isLoading布尔值用于跟踪是否正在加载更多数据。
  6. 构建滚动视图
    • 使用InfiniteScrollView.builder构建列表。
    • itemCount根据当前项目数量和加载状态动态计算。
    • itemBuilder根据索引构建列表项,如果索引超出当前项目数量,则显示加载指示器。
    • onLoadMore回调用于加载更多数据,模拟网络请求延迟,然后向items列表添加更多项目。

这个示例展示了如何使用infinite_scroll_view插件来实现基本的无限滚动列表。你可以根据需要进一步自定义和扩展这个示例。

回到顶部