概要
Flutterでのいろいろなリストの作り方まとめ
普通のリスト
「ListVIew.builder」を使用する
class NormalListScreen extends StatelessWidget {
const NormalListScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final _data = ['data1', 'data2', 'data3', 'data4', 'data5'];
return ListView.builder(
itemCount: _data.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text(_data[index]),
);
});
}
}
区切り線付きのリスト
「ListView.separated」を使用する
class SeparatedListScreen extends StatelessWidget {
const SeparatedListScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final _data = ['data1', 'data2', 'data3', 'data4', 'data5'];
return ListView.separated(
itemCount: _data.length,
separatorBuilder: (BuildContext context, int index) {
return const Divider(
color: Colors.grey,
indent: 10,
endIndent: 10,
);
},
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text(_data[index]),
);
});
}
}
スワイプで削除できるリスト
「Dismissible」ウィジェットを使用する
class DismissibleListScreen extends StatelessWidget {
const DismissibleListScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final _data = ['data1', 'data2', 'data3', 'data4', 'data5'];
return ListView.builder(
itemCount: _data.length,
itemBuilder: (BuildContext context, int index) {
return Dismissible(
key: Key(_data[index]),
background: Container(
color: Colors.red,
),
confirmDismiss: (direction) async {
// 削除の確認
// falseの場合削除できない
return true;
},
onDismissed: (direction) {
// 削除が完了し、リサイズ終了時に呼ばれる
},
child: ListTile(
title: Text(_data[index]),
),
);
});
}
}
アニメーション付きリスト
「AnimatedList」を使用する
class SizeAnimatedListScreen extends StatefulWidget {
const SizeAnimatedListScreen({Key? key}) : super(key: key);
@override
State<SizeAnimatedListScreen> createState() => SizeAnimatedListScreenState();
}
class SizeAnimatedListScreenState extends State<SizeAnimatedListScreen> {
final GlobalKey<AnimatedListState> _listKey = GlobalKey();
final _data = ['data1', 'data2', 'data3', 'data4', 'data5'];
@override
Widget build(BuildContext context) {
return AnimatedList(
key: _listKey,
initialItemCount: _data.length,
itemBuilder: (context, index, animation) {
return _buildItem(_data[index], animation);
},
);
}
Widget _buildItem(String item, Animation<double> animation) {
return SizeTransition(
sizeFactor: animation,
child: ListTile(
title: Text(item),
onTap: () {
int insertIndex = _data.length;
_data.add('data' + (insertIndex + 1).toString());
_listKey.currentState?.insertItem(insertIndex,
duration: const Duration(milliseconds: 100));
},
onLongPress: () {
int removeIndex = _data.indexOf(item);
_data.removeAt(removeIndex);
_listKey.currentState?.removeItem(removeIndex, (context, animation) {
return _buildItem(item, animation);
}, duration: const Duration(milliseconds: 100));
},
),
);
}
}
スライド動作させる場合は↓
class SlideAnimatedListScreen extends StatefulWidget {
const SlideAnimatedListScreen({Key? key}) : super(key: key);
@override
State<SlideAnimatedListScreen> createState() =>
SlideAnimatedListScreenState();
}
class SlideAnimatedListScreenState extends State<SlideAnimatedListScreen> {
final GlobalKey<AnimatedListState> _listKey = GlobalKey();
final _data = ['data1', 'data2', 'data3', 'data4', 'data5'];
@override
Widget build(BuildContext context) {
return AnimatedList(
key: _listKey,
initialItemCount: _data.length,
itemBuilder: (context, index, animation) {
return _buildItem(_data[index], animation);
},
);
}
Widget _buildItem(String item, Animation<double> animation) {
return SlideTransition(
position: animation.drive(
Tween<Offset>(begin: const Offset(1.0, 0), end: Offset.zero)
.chain(CurveTween(curve: Curves.bounceInOut))),
child: ListTile(
title: Text(item),
onTap: () {
int insertIndex = _data.length;
_data.add('data' + (insertIndex + 1).toString());
_listKey.currentState?.insertItem(insertIndex,
duration: const Duration(milliseconds: 200));
},
onLongPress: () {
int removeIndex = _data.indexOf(item);
_data.removeAt(removeIndex);
_listKey.currentState?.removeItem(removeIndex, (context, animation) {
return _buildItem(item, animation);
}, duration: const Duration(milliseconds: 200));
},
),
);
}
}