flutter3.0学习笔记

动画列表AnimatedList

Preview

AnimatedList 可以在列表中插入或删除节点时执行一个动画,在需要添加或删除列表项的场景中会提高用户体验。先看一下AnimatedList的构造:

const AnimatedList({
   super.key,
   required this.itemBuilder,//滚动到视图中时在列表中构建项目
   this.initialItemCount = 0,//ch
   this.scrollDirection = Axis.vertical,
   this.reverse = false,
   this.controller,
   this.primary,
   this.physics,
   this.shrinkWrap = false,
   this.padding,
   this.clipBehavior = Clip.hardEdge,
 })

AnimatedList 是一个 StatefulWidget,它对应的 State 类型为 AnimatedListState,添加和删除元素的方法位于 AnimatedListState 中:

void insertItem(int index, { Duration duration = _kDuration });

void removeItem(int index, AnimatedListRemovedItemBuilder builder, { Duration duration = _kDuration }) ;

获取AnimatedListState的两种方法:

  • 通过设置key: 例子:
import 'package:flutter/material.dart';
class AnimatedListPage extends StatefulWidget {
  const AnimatedListPage({Key? key}) : super(key: key);

  @override
  State<AnimatedListPage> createState() => _AnimatedListPageState();
}

class _AnimatedListPageState extends State<AnimatedListPage> {
  final _items = [];
  final _key = GlobalKey<AnimatedListState>();
  //添加
  void _addItem() {
    _items.insert(0, 'Item ${_items.length + 1}');
    _key.currentState!.insertItem(0,duration: const Duration(seconds: 1));
  }
  //删除
  void _removeItem(int index){
    _key.currentState!.removeItem(index, (context, animation)  {
      return SizeTransition(
        sizeFactor: animation,
        child: const Card(
          margin:  EdgeInsets.all(10),
          elevation: 10,
          color: Colors.purple,
          child: ListTile(
            contentPadding: EdgeInsets.all(15),
            title: Text('删除'),
          ),
        )
      );
    },duration: const Duration(seconds: 1));
    _items.removeAt(index);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('使用key的方法'),),
      body: AnimatedList(
        key: _key,
        initialItemCount: 0,
        padding: const EdgeInsets.all(10),
        itemBuilder: (context,index,animation){
          return SizeTransition(
            sizeFactor: animation,
            child: Card(
              margin: const EdgeInsets.all(10),
              elevation: 10,
              color: Colors.orange,
              child: ListTile(
                contentPadding: const EdgeInsets.all(15),
                title: Text(_items[index]),
                trailing: IconButton(
                  icon:const Icon(Icons.delete),
                  onPressed: ()=>_removeItem(index),
                ),
              ),
            ),
          );
        },
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _addItem,child: const Icon(Icons.add),
      ),
    );
  }
}

image.png

  • 通过AnimatedList.of(context)方法 例子:
import 'package:flutter/material.dart';

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

  @override
  State<AnimatedListPage> createState() => _AnimatedListPageState();
}

class _AnimatedListPageState extends State<AnimatedListPage> {
  final _items = ["Item 0"];
  final _key = GlobalKey<AnimatedListState>();
  //添加
  void _addItem() {
    _items.insert(0, 'Item ${_items.length + 1}');
    _key.currentState!.insertItem(0,duration: const Duration(seconds: 1));
  }
  //删除
  void _removeItem(int index,BuildContext context) {
    AnimatedList.of(context).removeItem(index, (context, animation) {
      return FadeTransition(
          opacity: animation,
          child: SizeTransition(
            sizeFactor: animation,
            child: SizedBox(
              height: 150,
              child: Card(
                margin: const EdgeInsets.symmetric(vertical: 20),
                elevation: 10,
                color: Colors.red[400],
                child: const Center(
                  child: Text('list',style: TextStyle(fontSize: 28),),
                ),
              ),
            ),
          ),
      );
    } ,duration: const Duration(seconds: 1));
    _items.removeAt(index);
  }
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('AnimatedList.of'),
        actions: [
          IconButton(
              onPressed: _addItem,
              icon: const Icon(Icons.plus_one_outlined),
          )
        ],
      ),
      body: AnimatedList(
        key: _key,
        initialItemCount: 1,
        padding: const EdgeInsets.all(10),
        itemBuilder: (context,index, animation){
          return SlideTransition(
              position: Tween<Offset>(
                begin: const Offset(-1, -0.5),
                end:const Offset(0, 0),
              ).animate(animation),
              child: RotationTransition(
                turns: animation,
                child: SizeTransition(
                  axis: Axis.vertical,
                  sizeFactor: animation,
                  child: SizedBox(
                    height: 150,
                    child: InkWell(
                      onTap: ()=>_removeItem(index, context),
                      child: Card(
                        margin: const EdgeInsets.symmetric(vertical: 20),
                        elevation: 10,
                        color: Colors.primaries[(index*100)% Colors.primaries.length][300],
                        child: Center(
                          child: Text(_items[index],style: const TextStyle(fontSize: 28),),
                        ),
                      ),
                    ),
                  ),
                ),
              ),
          );
        },
      ),
    );
  }
}

image.png