Flutter:ListView结合MaterialPageRoute实现不同项跳转对应页面
实现ListView列表项跳转对应页面的方案
方法一:扩展数据模型(推荐,扩展性强)
给你的Category类新增一个属性,用来存储对应页面的构造逻辑,让每个列表项的数据本身绑定目标页面:
// 修改Category类 class Category { final String name; final String imgName; final Widget Function() pageBuilder; // 新增页面构造器属性 Category({ required this.name, required this.imgName, required this.pageBuilder, }); }
初始化categories列表时,给每个项指定对应的页面:
// 示例初始化代码 final List<Category> categories = [ Category( name: 'ExamplePage', imgName: 'example_img', pageBuilder: () => ExamplePage(), ), Category( name: 'TestPage', imgName: 'test_img', pageBuilder: () => TestPage(), ), ];
最后修改GestureDetector的onTap逻辑:
Expanded( child: ListView.builder( itemCount: categories.length, itemBuilder: (BuildContext ctx, int index) { return GestureDetector( onTap: () { Navigator.of(context).push( MaterialPageRoute( builder: (BuildContext context) { // 调用当前项的pageBuilder返回目标页面 return categories[index].pageBuilder(); }, ), ); }, child: Container( margin: const EdgeInsets.all(20), height: 150, child: Stack( children: [ Positioned.fill( child: ClipRRect( borderRadius: BorderRadius.circular(20), child: Image.asset( 'images/${categories[index].imgName}.png', fit: BoxFit.cover), ), ), Positioned( bottom: 0, child: Padding( padding: const EdgeInsets.all(10.0), child: Text( categories[index].name, style: const TextStyle(fontSize: 25), ) ), ) ], ), ), ); }, ), )
方法二:使用页面映射表(无需修改数据模型)
如果不想改动Category类,可以创建名称与页面的映射关系,通过列表项的name字段匹配对应页面:
Expanded( child: ListView.builder( itemCount: categories.length, itemBuilder: (BuildContext ctx, int index) { // 定义名称到页面的映射 final Map<String, Widget Function()> pageMap = { 'ExamplePage': () => ExamplePage(), 'TestPage': () => TestPage(), // 可继续添加更多页面映射 }; return GestureDetector( onTap: () { // 根据当前项的name获取对应页面,默认返回ExamplePage防止匹配失败 final targetPage = pageMap[categories[index].name] ?? () => ExamplePage(); Navigator.of(context).push( MaterialPageRoute( builder: (BuildContext context) => targetPage(), ), ); }, child: Container( margin: const EdgeInsets.all(20), height: 150, child: Stack( children: [ Positioned.fill( child: ClipRRect( borderRadius: BorderRadius.circular(20), child: Image.asset( 'images/${categories[index].imgName}.png', fit: BoxFit.cover), ), ), Positioned( bottom: 0, child: Padding( padding: const EdgeInsets.all(10.0), child: Text( categories[index].name, style: const TextStyle(fontSize: 25), ) ), ) ], ), ), ); }, ), )
内容的提问来源于stack exchange,提问作者TheJoniii
相关产品推荐
相关产品推荐

