Flutter动态添加动画列表插件animated_addition_listview的使用

Flutter动态添加动画列表插件animated_addition_listview的使用

由于 ListView 中存在不可调和的位置问题(比如从头部添加大高度数据时/手势滚动时无法精准定位位置而不导致闪烁,无法在滚动的过程中/非滚动结束流畅加载更多的头部数据),所以此库已经废弃,请使用 free_scroll_listview 替代。free_scroll_listview 将提供更流畅的加载方式和滚动动画。

动态添加动画列表插件 animated_addition_listview 的使用

示例代码

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

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const AnimatedAdditionTest(),
    );
  }
}

///animated addition test page
class AnimatedAdditionTest extends StatefulWidget {
  const AnimatedAdditionTest({super.key});

  @override
  State<StatefulWidget> createState() {
    return _AnimatedAdditionTestState();
  }
}

///animated addition test page state
class _AnimatedAdditionTestState extends State<AnimatedAdditionTest> {
  ///controller
  late AnimatedAdditionListViewController<String> _controller;

  @override
  void initState() {
    ///init controller
    _controller = AnimatedAdditionListViewController<String>(
      ///provide head data
      tailDataProvider: (String? current, int count) async {
        int number = (current != null ? int.parse(current) : 0) + 1;
        List<String> dataList = [];
        for (int s = number; s < number + count; s++) {
          dataList.add(s.toString());
        }
        return dataList;
      },

      ///provide current data
      headDataProvider: (String? current, int count) async {
        int number = (current != null ? int.parse(current) : 0);
        List<String> dataList = [];
        for (int s = number - count; s < number; s++) {
          dataList.add(s.toString());
        }
        dataList.removeWhere((e) => int.parse(e) <= 0);
        return dataList;
      },

      ///data list
      dataList: ["81", "82", "83", "84", "85", "86", "87", "88", "89", "90"],

      ///delta offset
      anchorOffset: 85 * 3,
    );

    ///load next items
    WidgetsBinding.instance.addPostFrameCallback((_) {
      _controller.loadHeadItems();
    });
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Material(
      color: Colors.red,
      child: SafeArea(
        top: true,
        bottom: true,
        child: Stack(
          children: [
            _buildTestPage(),
            _buildButton(),
          ],
        ),
      ),
    );
  }

  Widget _buildButton() {
    return Align(
      alignment: Alignment.bottomCenter,
      child: GestureDetector(
        behavior: HitTestBehavior.translucent,
        onTap: () {
          _controller.animateToItem("100");
        },
        child: Container(
          width: double.infinity,
          margin: const EdgeInsets.fromLTRB(30, 10, 30, 50),
          height: 30,
          decoration: BoxDecoration(
            color: Colors.blue,
            borderRadius: BorderRadius.circular(16),
          ),
        ),
      ),
    );
  }

  ///build test page
  Widget _buildTestPage() {
    return AnimatedAdditionListView(
      controller: _controller,
      padding: EdgeInsets.zero,
      reverse: true,
      physics: const BouncingScrollPhysics(),
      itemBuilder:
          (BuildContext context, int index, Animation<double> animation) {
        return SlideTransition(
          position: animation.drive(
            Tween<Offset>(
              begin: const Offset(-1, 0),
              end: const Offset(0, 0),
            ),
          ),
          child: Container(
            alignment: Alignment.center,
            width: double.infinity,
            decoration: const BoxDecoration(
              color: Colors.white,
              border: Border(
                bottom: BorderSide(color: Colors.black12, width: 0.3),
              ),
            ),
            height: 85,
            child: Text(
              _controller.dataList[index],
              style: const TextStyle(
                fontSize: 15,
                color: Colors.black,
                fontWeight: FontWeight.w500,
              ),
            ),
          ),
        );
      },
      onItemShow: (List<String> dataList) {
        print(dataList.join(","));
      },
    );
  }
}

使用说明

  1. 初始化控制器

    _controller = AnimatedAdditionListViewController<String>(
      tailDataProvider: (String? current, int count) async {
        int number = (current != null ? int.parse(current) : 0) + 1;
        List<String> dataList = [];
        for (int s = number; s < number + count; s++) {
          dataList.add(s.toString());
        }
        return dataList;
      },
      headDataProvider: (String? current, int count) async {
        int number = (current != null ? int.parse(current) : 0);
        List<String> dataList = [];
        for (int s = number - count; s < number; s++) {
          dataList.add(s.toString());
        }
        dataList.removeWhere((e) => int.parse(e) <= 0);
        return dataList;
      },
      dataList: ["81", "82", "83", "84", "85", "86", "87", "88", "89", "90"],
      anchorOffset: 85 * 3,
    );
    
  2. 加载更多数据

    WidgetsBinding.instance.addPostFrameCallback((_) {
      _controller.loadHeadItems();
    });
    
  3. 构建测试页面

    Widget _buildTestPage() {
      return AnimatedAdditionListView(
        controller: _controller,
        padding: EdgeInsets.zero,
        reverse: true,
        physics: const BouncingScrollPhysics(),
        itemBuilder: (BuildContext context, int index, Animation<double> animation) {
          return SlideTransition(
            position: animation.drive(
              Tween<Offset>(
                begin: const Offset(-1, 0),
                end: const Offset(0, 0),
              ),
            ),
            child: Container(
              alignment: Alignment.center,
              width: double.infinity,
              decoration: const BoxDecoration(
                color: Colors.white,
                border: Border(
                  bottom: BorderSide(color: Colors.black12, width: 0.3),
                ),
              ),
              height: 85,
              child: Text(
                _controller.dataList[index],
                style: const TextStyle(
                  fontSize: 15,
                  color: Colors.black,
                  fontWeight: FontWeight.w500,
                ),
              ),
            ),
          );
        },
        onItemShow: (List<String> dataList) {
          print(dataList.join(","));
        },
      );
    }
    
  4. 添加按钮以跳转到指定项

    Widget _buildButton() {
      return Align(
        alignment: Alignment.bottomCenter,
        child: GestureDetector(
          behavior: HitTestBehavior.translucent,
          onTap: () {
            _controller.animateToItem("100");
          },
          child: Container(
            width: double.infinity,
            margin: const EdgeInsets.fromLTRB(30, 10, 30, 50),
            height: 30,
            decoration: BoxDecoration(
              color: Colors.blue,
              borderRadius: BorderRadius.circular(16),
            ),
          ),
        ),
      );
    }
    

更多关于Flutter动态添加动画列表插件animated_addition_listview的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter动态添加动画列表插件animated_addition_listview的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


animated_addition_listview 是一个用于在 Flutter 中动态添加动画列表的插件。它允许你在列表中添加或删除项时,自动应用动画效果。以下是如何使用 animated_addition_listview 插件的简单示例。

1. 添加依赖

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

dependencies:
  flutter:
    sdk: flutter
  animated_addition_listview: ^1.0.0  # 使用最新版本

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

2. 导入包

在你的 Dart 文件中导入 animated_addition_listview 包:

import 'package:animated_addition_listview/animated_addition_listview.dart';

3. 使用 AnimatedAdditionListView

AnimatedAdditionListView 是一个带有动画效果的 ListView,它会在添加或删除项时自动应用动画。

以下是一个简单的示例,展示如何使用 AnimatedAdditionListView 动态添加和删除列表项:

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

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

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Animated Addition ListView Example'),
        ),
        body: AnimatedListExample(),
      ),
    );
  }
}

class AnimatedListExample extends StatefulWidget {
  [@override](/user/override)
  _AnimatedListExampleState createState() => _AnimatedListExampleState();
}

class _AnimatedListExampleState extends State<AnimatedListExample> {
  List<String> _items = ['Item 1', 'Item 2', 'Item 3'];

  void _addItem() {
    setState(() {
      _items.add('Item ${_items.length + 1}');
    });
  }

  void _removeItem(int index) {
    setState(() {
      _items.removeAt(index);
    });
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Column(
      children: [
        Expanded(
          child: AnimatedAdditionListView(
            itemCount: _items.length,
            itemBuilder: (context, index, animation) {
              return SizeTransition(
                sizeFactor: animation,
                child: Card(
                  margin: EdgeInsets.all(8.0),
                  child: ListTile(
                    title: Text(_items[index]),
                    trailing: IconButton(
                      icon: Icon(Icons.delete),
                      onPressed: () => _removeItem(index),
                    ),
                  ),
                ),
              );
            },
          ),
        ),
        Padding(
          padding: const EdgeInsets.all(8.0),
          child: ElevatedButton(
            onPressed: _addItem,
            child: Text('Add Item'),
          ),
        ),
      ],
    );
  }
}
回到顶部