Flutter高效列表滚动插件snappy_list_view的使用

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

Flutter高效列表滚动插件snappy_list_view的使用

SnappyListView 是一个用于在Flutter中实现高效列表滚动的插件,它允许列表中的每个元素在滚动时“吸附”到视口中心,类似于 PageView 的行为,但以列表形式展示。这个插件支持不同大小的项目,并提供了丰富的自定义选项。

主要特性

  • 不同和可变大小的项目:支持在滚动方向和正交方向上设置不同的大小。
  • 可配置的过滚动吸附物理效果:根据速度控制过滚动多个页面。
  • 列表可视化:可以选择或自定义多种显示方式,如轮盘、旋转木马、透视等。
  • 完全控制吸附位置:可以在视口和每个项目上指定吸附点。
  • 简单使用 PageController:获取反馈并控制列表。

重要提示

该部件的行为与 PageView 相同。这意味着在 ColumnStack 或其他地方使用时,其用法与 PageView 类似。

使用示例

以下是使用 SnappyListView 的完整示例代码:

import 'dart:math';
import 'package:flutter/material.dart';
import 'package:snappy_list_view/snappy_list_view.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: MyHomePage(),
    );
  }
}

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

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage>
    with TickerProviderStateMixin, AutomaticKeepAliveClientMixin {
  final List<YourSnappyWidget> yourContentList = List.generate(
      5, (index) => YourSnappyWidget.random(max: 300, min: 50));

  final PageController controller = PageController(initialPage: 0);
  late final TabController tabController;

  Axis axis = Axis.vertical;
  bool overscrollSnap = false;
  bool reverse = false;

  @override
  void initState() {
    controller.addListener(pageListener);
    tabController = TabController(length: 3, vsync: this);
    super.initState();
  }

  @override
  void dispose() {
    controller.removeListener(pageListener);
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    super.build(context);
    return Scaffold(
      appBar: AppBar(
        title: const Text('SnappyListView Demo'),
      ),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Expanded(
            child: SnappyListView(
              reverse: reverse,
              controller: controller,
              itemCount: yourContentList.length,
              itemSnapping: true,
              physics: const CustomPageViewScrollPhysics(),
              itemBuilder: (context, index) {
                final currentSnappyWidget = yourContentList.elementAt(index);
                return Container(
                  height: currentSnappyWidget.height,
                  width: currentSnappyWidget.width,
                  color: currentSnappyWidget.color,
                  child: Center(child: Text("Index: $index")),
                );
              },
              scrollDirection: axis,
            ),
          ),
          Text(
            "CurrentPage: ${controller.hasClients ? currentPage : 0}",
            style: Theme.of(context).textTheme.headlineMedium,
          ),
          Wrap(
            children: [
              TextButton(
                onPressed: () => setState(() =>
                    axis == Axis.horizontal ? current.width = randomSize : current.height = randomSize),
                child: const Text("Resize current"),
              ),
              TextButton(
                onPressed: () => setState(() => yourContentList.removeAt(currentPage!.round())),
                child: const Text("Delete current"),
              ),
              TextButton(
                onPressed: () => setState(() => yourContentList.insert(
                    currentPage!.round() + 1, YourSnappyWidget.random())),
                child: const Text("Insert after current"),
              ),
              TextButton(
                onPressed: () => controller.animateToPage(0,
                    duration: const Duration(milliseconds: 1200), curve: Curves.linear),
                child: const Text("Animate to first"),
              ),
              TextButton(
                onPressed: () => setState(() =>
                    axis == Axis.horizontal ? axis = Axis.vertical : axis = Axis.horizontal),
                child: const Text("Change axis "),
              ),
              TextButton(
                onPressed: () => setState(() => reverse = !reverse),
                child: const Text("Reverse"),
              ),
            ],
          )
        ],
      ),
    );
  }

  double get randomSize => Random().nextInt(300).clamp(100, 300).toDouble();

  YourSnappyWidget get current => yourContentList.elementAt(currentPage!.round());

  double? get currentPage => controller.hasClients
      ? double.parse(controller.page!.toStringAsFixed(3))
      : null;

  void pageListener() => setState(() {});

  @override
  bool get wantKeepAlive => true;
}

class YourSnappyWidget {
  double width;
  double height;
  Color color;

  YourSnappyWidget({
    required this.color,
    required this.width,
    required this.height,
  });

  YourSnappyWidget.random({int max = 300, int min = 100})
      : width = Random().nextInt(max).clamp(min, max).toDouble(),
        height = Random().nextInt(max).clamp(min, max).toDouble(),
        color = Colors.accents.elementAt(Random().nextInt(Colors.accents.length));
}

class CustomPageViewScrollPhysics extends ScrollPhysics {
  const CustomPageViewScrollPhysics({ScrollPhysics? parent}) : super(parent: parent);

  @override
  CustomPageViewScrollPhysics applyTo(ScrollPhysics? ancestor) {
    return CustomPageViewScrollPhysics(parent: buildParent(ancestor)!);
  }

  @override
  SpringDescription get spring => const SpringDescription(
        mass: 50,
        stiffness: 100,
        damping: 0.8,
      );
}

主要参数说明

  • int itemCount:项目的总数。
  • Widget Function(BuildContext, int) itemBuilder:构建项目的回调函数。
  • PageController controller:用于控制滚动和获取当前页面信息。
  • ScrollPhysics? physics:自定义滚动物理属性。
  • bool itemSnapping:是否启用项目吸附。
  • bool reverse:是否反转列表。
  • ItemPositionsListener itemPositionsListener:监听项目在视口中的精确位置。
  • void Function(int index, double size)? onPageChanged:当当前改变索引和大小时获取反馈。

通过上述示例和参数说明,您可以轻松地在Flutter应用中集成并使用 SnappyListView 插件,实现高效的列表滚动效果。


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

1 回复

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


当然,以下是如何在Flutter中使用snappy_list_view插件来实现高效列表滚动的示例代码。snappy_list_view是一个用于优化滚动性能的Flutter插件,尤其适用于包含大量数据的列表。

首先,确保你已经在pubspec.yaml文件中添加了snappy_list_view的依赖:

dependencies:
  flutter:
    sdk: flutter
  snappy_list_view: ^x.y.z  # 请替换为最新版本号

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

接下来,是一个简单的示例代码,展示了如何使用snappy_list_view来创建一个高效的滚动列表:

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

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

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

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final List<String> items = List.generate(1000, (index) => "Item $index");

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('SnappyListView Demo'),
      ),
      body: SnappyListView.builder(
        itemCount: items.length,
        itemBuilder: (context, index) {
          return ListTile(
            title: Text(items[index]),
          );
        },
        // 可选配置,用于优化滚动性能
        itemExtent: 56.0, // 每个item的高度,如果item高度固定,设置这个值可以提高性能
        // physics: ClampingScrollPhysics(), // 自定义滚动物理效果
      ),
    );
  }
}

在这个示例中:

  1. 我们首先创建了一个包含1000个项目的列表items
  2. 使用SnappyListView.builder方法来构建列表。builder方法接受三个参数:
    • itemCount:列表中的项目总数。
    • itemBuilder:一个函数,用于构建每个列表项。它接受两个参数:contextindex,并返回一个Widget
    • itemExtent:每个列表项的高度(可选)。如果列表项的高度是固定的,设置这个值可以显著提高滚动性能。

你可以根据需求调整itemExtent的值,如果列表项的高度不固定,可以省略这个参数。

这个示例展示了如何使用snappy_list_view来创建一个高效的滚动列表。如果你需要进一步优化性能,可以考虑使用其他配置,如自定义滚动物理效果等。

回到顶部