Flutter中点击SfDataGrid行跳转至用户详情页的实现方法
实现SfDataGrid行点击跳转到用户详情页(Firestore数据源)
核心思路
通过给SfDataGrid绑定行点击回调,获取选中行的用户ID(或完整用户对象),再用MaterialPageRoute跳转到详情页,最终基于ID从Firestore拉取完整信息展示。
步骤1:给SfDataGrid添加行点击事件
利用SfDataGrid的onRowTap回调获取点击行的用户数据,触发页面跳转:
SfDataGrid( source: _userDataSource, columns: [ GridColumn(columnName: 'name', label: const Text('姓名')), GridColumn(columnName: 'email', label: const Text('邮箱')), // 其他列定义 ], // 行点击回调 onRowTap: (RowTapDetails details) { // 从数据源中拿到选中的用户对象 final UserModel selectedUser = _userDataSource.data[details.rowIndex]; // 跳转到详情页 Navigator.push( context, MaterialPageRoute( // 传递用户ID或完整对象,二选一即可 builder: (context) => UserDetailScreen(userId: selectedUser.id), // builder: (context) => UserDetailScreen(user: selectedUser), ), ); }, )
步骤2:确保DataGridSource保留完整用户数据
自定义DataGridSource时,要存储完整的用户对象(包含Firestore文档ID),方便点击时直接获取:
class UserDataSource extends DataGridSource { UserDataSource(this.data) { _buildRows(); } // 存储完整的用户列表 final List<UserModel> data; late List<DataGridRow> _rows; void _buildRows() { _rows = data.map((user) { return DataGridRow(cells: [ DataGridCell<String>(columnName: 'name', value: user.name), DataGridCell<String>(columnName: 'email', value: user.email), // 其他对应列的单元格数据 ]); }).toList(); } @override List<DataGridRow> get rows => _rows; @override DataGridRowAdapter buildRow(DataGridRow row) { return DataGridRowAdapter( cells: row.getCells().map((cell) { return Container( alignment: Alignment.center, padding: const EdgeInsets.all(8), child: Text(cell.value.toString()), ); }).toList(), ); } }
同时,从Firestore拉取数据时要保存文档ID到用户实体类:
// 用户实体类 class UserModel { final String id; final String name; final String email; // 其他字段 UserModel({ required this.id, required this.name, required this.email, // 其他字段初始化 }); } // 从Firestore获取用户数据的方法 Future<List<UserModel>> fetchUsers() async { final snapshot = await FirebaseFirestore.instance.collection('users').get(); return snapshot.docs.map((doc) { return UserModel( id: doc.id, // 保存Firestore文档ID name: doc['name'], email: doc['email'], // 映射其他字段 ); }).toList(); }
步骤3:实现用户详情页
两种实现方式,选其一即可:
方式1:通过ID从Firestore重新拉取数据
适合用户信息可能实时更新的场景:
class UserDetailScreen extends StatelessWidget { final String userId; const UserDetailScreen({super.key, required this.userId}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('用户详情')), body: FutureBuilder<DocumentSnapshot>( future: FirebaseFirestore.instance.collection('users').doc(userId).get(), builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return const Center(child: CircularProgressIndicator()); } if (!snapshot.hasData || !snapshot.data!.exists) { return const Center(child: Text('用户不存在')); } final userData = snapshot.data!.data() as Map<String, dynamic>; return Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('姓名: ${userData['name']}', style: const TextStyle(fontSize: 18)), const SizedBox(height: 8), Text('邮箱: ${userData['email']}', style: const TextStyle(fontSize: 18)), const SizedBox(height: 8), Text('电话: ${userData['phone'] ?? '无'}', style: const TextStyle(fontSize: 18)), // 展示更多用户字段 ], ), ); }, ), ); } }
方式2:直接传递完整用户对象
适合数据量小、无需实时更新的场景,无需再次请求Firestore:
class UserDetailScreen extends StatelessWidget { final UserModel user; const UserDetailScreen({super.key, required this.user}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text(user.name)), body: Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('邮箱: ${user.email}', style: const TextStyle(fontSize: 18)), const SizedBox(height: 8), Text('电话: ${user.phone ?? '无'}', style: const TextStyle(fontSize: 18)), // 直接使用user对象的字段展示 ], ), ), ); } }
内容的提问来源于stack exchange,提问作者Ageu Chamene
相关产品推荐
相关产品推荐

