Flutter中如何制作带动态Trailing的自定义Widget?
为不同页面自定义MyCard的Trailing按钮
要实现三个页面(全部电影、收藏电影、已删除电影)的MyCard显示不同的Trailing按钮布局,我们可以给MyCard添加页面类型标识,根据标识动态渲染对应的按钮组件。具体实现步骤如下:
1. 定义页面类型枚举
先创建一个枚举来区分三个页面的类型:
enum MoviePageType { allMovies, favMovies, deletedMovies }
2. 修改MyCard组件
更新MyCard的参数,添加页面类型、可选的删除和恢复回调,然后根据页面类型生成对应的Trailing按钮列表:
class MyCard extends StatelessWidget { final Movie e; final VoidCallback? taponfav; final VoidCallback? tapondel; final VoidCallback? taponRestore; final MoviePageType pageType; MyCard({ required this.e, this.taponfav, this.tapondel, this.taponRestore, required this.pageType, }); @override Widget build(BuildContext context) { return Card( child: ListTile( title: Text(e.name.toString()), subtitle: Text(e.language), trailing: _buildTrailingButtons(), leading: CircleAvatar( backgroundImage: NetworkImage(e.imageurl), ), ), ); } Widget _buildTrailingButtons() { List<Widget> buttons = []; switch (pageType) { case MoviePageType.allMovies: // 全部电影页:显示收藏+删除按钮 if (taponfav != null) { buttons.add( IconButton( icon: userlist[0].favmovies.contains(e) ? const Icon(Icons.favorite) : const Icon(Icons.favorite_outline), onPressed: taponfav, ), ); } if (tapondel != null) { buttons.add( IconButton( icon: const Icon(Icons.delete), onPressed: tapondel, ), ); } break; case MoviePageType.favMovies: // 收藏电影页:仅显示收藏按钮 if (taponfav != null) { buttons.add( IconButton( icon: const Icon(Icons.favorite), onPressed: taponfav, ), ); } break; case MoviePageType.deletedMovies: // 已删除电影页:显示恢复+永久删除按钮 if (taponRestore != null) { buttons.add( IconButton( icon: const Icon(Icons.restore), onPressed: taponRestore, ), ); } if (tapondel != null) { buttons.add( IconButton( icon: const Icon(Icons.delete_forever), onPressed: tapondel, ), ); } break; } return Row( mainAxisSize: MainAxisSize.min, children: buttons, ); } }
3. 各页面使用MyCard示例
全部电影页
body: ListView( children: movielist .map((e) => MyCard( e: e, pageType: MoviePageType.allMovies, taponfav: () { if (userlist[0].favmovies.contains(e)) { userlist[0].favmovies.remove(e); } else { userlist[0].favmovies.add(e); } setState(() {}); }, tapondel: () { showDialog( context: context, builder: (ctx) { return AlertDialog( title: const Text('确定要删除吗?'), actions: [ TextButton( onPressed: () { Navigator.of(ctx).pop(); userlist[0].deletedmovies.add(e); movielist.remove(e); setState(() {}); ScaffoldMessenger.of(context).showSnackBar( SnackBar( duration: const Duration(seconds: 4), content: Text('${e.name} 已删除'), ), ); }, child: const Text('确定'), ), TextButton( onPressed: () { Navigator.of(ctx).pop(); }, child: const Text('取消'), ), ], ); }, ); }, )) .toList(), ),
收藏电影页
body: ListView( children: userlist[0].favmovies .map((e) => MyCard( e: e, pageType: MoviePageType.favMovies, taponfav: () { userlist[0].favmovies.remove(e); setState(() {}); }, )) .toList(), ),
已删除电影页
body: ListView( children: userlist[0].deletedmovies .map((e) => MyCard( e: e, pageType: MoviePageType.deletedMovies, taponRestore: () { userlist[0].deletedmovies.remove(e); movielist.add(e); setState(() {}); ScaffoldMessenger.of(context).showSnackBar( SnackBar( duration: const Duration(seconds: 4), content: Text('${e.name} 已恢复'), ), ); }, tapondel: () { showDialog( context: context, builder: (ctx) { return AlertDialog( title: const Text('确定要永久删除吗?'), actions: [ TextButton( onPressed: () { Navigator.of(ctx).pop(); userlist[0].deletedmovies.remove(e); setState(() {}); ScaffoldMessenger.of(context).showSnackBar( SnackBar( duration: const Duration(seconds: 4), content: Text('${e.name} 已永久删除'), ), ); }, child: const Text('确定'), ), TextButton( onPressed: () { Navigator.of(ctx).pop(); }, child: const Text('取消'), ), ], ); }, ); }, )) .toList(), ),
通过以上修改,每个页面的MyCard会根据对应的类型渲染正确的Trailing按钮,同时保持组件的复用性。
内容的提问来源于stack exchange,提问作者Irfan Ganatra
相关产品推荐
相关产品推荐

