AnimatedList
は、状態を持つウィジェットであり、対応する State の型はAnimatedListState
です。
AnimatedList の構造は以下の通りです:
const AnimatedList({
Key? key,
required Widget Function(BuildContext, int, Animation<double>) itemBuilder,//データの構築者
int initialItemCount = 0,//初期データの総数
Axis scrollDirection = Axis.vertical,//スクロール方向
bool reverse = false,//下から上に表示するかどうか
ScrollController? controller,//スクロールのコントローラー、オプション、リストのスクロール位置を制御します
bool? primary,//親スクロールに関連付けるかどうか
ScrollPhysics? physics,//ユーザー操作への応答方法
bool shrinkWrap = false,
EdgeInsetsGeometry? padding,//内部余白
Clip clipBehavior = Clip.hardEdge,
})
State には、リスト内の要素を追加および削除するための 2 つのメソッドがあります:
注意:リストがデータソースのリストにバインドされている場合、要素を直接削除または追加してリストを更新することはできません。以下のメソッドを実行する必要があります:
//要素を挿入
void insertItem(
int index,
{Duration duration = _kDuration}
)
//要素を削除
void removeItem(
int index,
Widget Function(BuildContext, Animation<double>) builder, {
Duration duration = _kDuration,
})
追加および削除の際には、指定されたアニメーションが表示されます
insertItem、removeItem を使用する場合、通常は globalKey と組み合わせる必要がありますが、globalKey にはジェネリック型を指定する必要があります。これにより、リストの要素を追加および削除するメソッドを呼び出すことができます:
final globalKey = GlobalKey<AnimatedListState>();
要素を追加する場合は、次のようにします:
list.add("新しいデータ");
globalKey.currentState!.insertItem(list.length - 1);
要素を削除する場合は、少し複雑です。要素がフェードアウトするアニメーションが表示された後に、対応するデータソースのエントリを削除する必要があります。
通常、
_buildItem
メソッドを作成して、子要素を動的に作成し、removeItem
を実行する際には、コールバック内で同じ子要素を作成し、フェードアウトアニメーションを使用して表示し、最後にデータ配列から削除します。
//要素を削除
_delItem(index) {
globalKey.currentState!.removeItem(index, (context, animation) {
//削除する要素を取得し、フェードアウト表示する
var removeItem = _buildItem(index);
return FadeTransition(
//アニメーションを実行
opacity: animation,
child: removeItem,
);
});
list.removeAt(index); //データ配列から削除
}
完全なコード#
//AnimatedList
class HomePage extends StatefulWidget {
const HomePage({super.key});
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
//globalKeyを定義
final globalKey = GlobalKey<AnimatedListState>();
List<String> list = ["最初のデータ", "2番目のデータ"];
bool flag = true;
Widget _buildItem(index) {
return ListTile(
title: Text(list[index]),
trailing: IconButton(
icon: const Icon(Icons.delete),
onPressed: () {
//削除を実行
_delItem(index);
},
),
);
}
//要素を削除
_delItem(index) {
globalKey.currentState!.removeItem(index, (context, animation) {
//削除する要素を取得し、フェードアウト表示する
var removeItem = _buildItem(index);
list.removeAt(index); //データ配列から削除
return FadeTransition(
//アニメーションを実行
opacity: animation,
child: removeItem,
);
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text("kano")),
floatingActionButton: FloatingActionButton(
child: const Icon(Icons.add),
//このままではlistを操作してもAnimatedListには反映されない
onPressed: () {
// setState(() {
// list.add("新しいデータ");
// });
///AnimatedListのinsertItemメソッドを使用する
list.add("新しいデータ");
globalKey.currentState!.insertItem(list.length - 1);
},
),
//アニメーション付きのリスト
body: AnimatedList(
key: globalKey,
initialItemCount: list.length,
itemBuilder: (context, index, animation) {
//フェードの遷移 opacity 入るときは0から1、出るときはその逆
return FadeTransition(opacity: animation);
//スケールの遷移
// return ScaleTransition(scale: animation);
},
),
);
}
}