Flutter路由映射问题:Navigator.pushNamed触发index未定义错误
Flutter GridView 项点击跳转错误:index未定义的解决方法
错误原因分析
- index作用域问题:你把
GestureDetector放在了GridView.builder外面,这里的index是itemBuilder的局部参数,外层onTap根本访问不到该变量,所以报"index未定义"。 - 路由参数类型错误:
masterMap里的destination值不统一,有的是路由名称(比如InputRaw.id),有的直接传了InputRaw()(Widget实例),而Navigator.pushNamed需要传入命名路由的字符串名称,不能传Widget对象。
解决步骤
1. 统一路由名称格式
先确保每个页面都定义静态路由id(以InputRaw为例):
// 在InputRaw页面中添加静态路由标识 class InputRaw extends StatelessWidget { static const id = '/inputRaw'; // ... 页面其他代码 }
然后将masterMap里的destination全部改为对应的路由名称字符串:
final List<Map<String, dynamic>> masterMap = [ {'image': 'assets/images/raw.png', 'title': 'Input Raw', 'destination': InputRaw.id}, {'image': 'assets/images/supplier.png', 'title': 'Input Supplier', 'destination': '/inputSupplier'}, {'image': 'assets/images/cmt.png', 'title': 'Input CMT', 'destination': '/inputCMT'}, // ... 其他项同理修改为对应页面的路由名称 ];
2. 将点击事件移到每个网格项内部
把GestureDetector从GridView.builder外层移到itemBuilder内部,这样就能直接获取当前项的index:
修改后的完整代码:
import 'package:egarment2/pages/master_menu/input_raw.dart'; import 'package:flutter/material.dart'; class FeatureCard extends StatefulWidget { const FeatureCard({Key? key}) : super(key: key); @override State<FeatureCard> createState() => _FeatureCardState(); } class _FeatureCardState extends State<FeatureCard> { final List<Map<String, dynamic>> masterMap = [ {'image': 'assets/images/raw.png', 'title': 'Input Raw', 'destination': InputRaw.id}, {'image': 'assets/images/supplier.png', 'title': 'Input Supplier', 'destination': '/inputSupplier'}, {'image': 'assets/images/cmt.png', 'title': 'Input CMT', 'destination': '/inputCMT'}, {'image': 'assets/images/pola.png', 'title': 'Input Pola', 'destination': '/inputPola'}, {'image': 'assets/images/outlet.png', 'title': 'Input Outlet', 'destination': '/inputOutlet'}, {'image': 'assets/images/product.png', 'title': 'Input Produk', 'destination': '/inputProduk'}, {'image': 'assets/images/material.png', 'title': 'Input Jenis Material', 'destination': '/inputMaterial'}, {'image': 'assets/images/warna.png', 'title': 'Input Warna', 'destination': '/inputWarna'}, {'image': 'assets/images/qr.png', 'title': 'Input by QR', 'destination': '/inputQR'}, {'image': 'assets/images/acc.png', 'title': 'Accessories', 'destination': '/inputAccessories'}, {'image': 'assets/images/tools.png', 'title': 'Tools & Equipment', 'destination': '/inputTools'}, {'image': 'assets/images/adjustment.png', 'title': 'Adjustments', 'destination': '/inputAdjustment'}, {'image': 'assets/images/stock.png', 'title': 'Stock Opname', 'destination': '/inputStock'}, ]; @override Widget build(BuildContext context) { return GridView.builder( gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, crossAxisSpacing: 12.0, mainAxisSpacing: 12.0, ), itemCount: masterMap.length, itemBuilder: (_, index) { return GestureDetector( onTap: () { String routeName = masterMap[index]['destination']; Navigator.pushNamed(context, routeName); }, child: Padding( padding: const EdgeInsets.only(top: 40), child: Container( height: 175, width: 150, decoration: BoxDecoration( borderRadius: BorderRadius.circular(20), color: Colors.white, ), child: Column( children: [ Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), ), child: Image.asset(masterMap[index]['image']), ), Text( masterMap[index]['title'], style: const TextStyle( fontFamily: 'Quicksand', ), ), ], ), ), ), ); }, ); } }
额外提示
- 务必在
MaterialApp的routes参数中注册所有用到的命名路由:
MaterialApp( routes: { InputRaw.id: (context) => const InputRaw(), '/inputSupplier': (context) => const InputSupplier(), // ... 其他页面路由注册 }, );
- 访问列表元素时,
masterMap[index]['key']比masterMap.elementAt(index)['key']更简洁直观。
内容的提问来源于stack exchange,提问作者Bryant Anthony
相关产品推荐
相关产品推荐

