Flutter中如何从TextFormField获取Icon和Color类型的值?
问题
我尝试创建一个表单用于生成新的Satisfacao对象,但需要从TextFormField中获取非字符串类型的值。期望在Color输入框输入"Colors.red"、Icon输入框输入"Icons.save"并提交表单后,_submitForm函数能创建包含对应Color和Icon参数的对象,示例如下:
Satisfacao( id: 's1', title: 'Muito Boa', color: Colors.red, icon: Icons.save, count: 0, )
我尝试了如下代码但无法正常运行:
Satisfacao类代码
import 'package:flutter/material.dart'; class Satisfacao with ChangeNotifier { final String id; final String title; final Color color; final IconData icon; int count; Satisfacao({ required this.id, required this.title, this.color = Colors.orange, required this.icon, this.count = 0, }); }
表单页面代码
import 'dart:ffi'; import 'package:apetit_project/models/satisfacao.dart'; import 'package:flutter/material.dart'; class SatisfactionFormScreen extends StatefulWidget { const SatisfactionFormScreen({Key? key}) : super(key: key); @override State<SatisfactionFormScreen> createState() => _SatisfactionFormScreenState(); } class _SatisfactionFormScreenState extends State<SatisfactionFormScreen> { final _titleFocus = FocusNode(); final _colorFocus = FocusNode(); final _iconFocus = FocusNode(); final _formKey = GlobalKey<FormState>(); final _formData = Map<String, Object>(); @override void dispose() { super.dispose(); _titleFocus.dispose(); } void _submitForm() { _formKey.currentState?.save(); final newSatisfacao = Satisfacao( id: _formData['id'] as String, title: _formData['title'] as String, color: _formData['color'] as Color, icon: _formData['icon'] as IconData, ); print(newSatisfacao.id); print(newSatisfacao.title); print(newSatisfacao.color); print(newSatisfacao.icon); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Formulário de Satisfação'), actions: [ IconButton( onPressed: _submitForm, icon: Icon(Icons.save), ), ], ), body: Padding( padding: const EdgeInsets.all(15), child: Form( key: _formKey, child: ListView( children: [ TextFormField( decoration: const InputDecoration(labelText: 'Id'), textInputAction: TextInputAction.next, onFieldSubmitted: (_) { FocusScope.of(context).requestFocus(_titleFocus); }, onSaved: (id) => _formData['id'] = id ?? '', ), TextFormField( decoration: const InputDecoration(labelText: 'Title'), textInputAction: TextInputAction.next, focusNode: _titleFocus, onFieldSubmitted: (_) { FocusScope.of(context).requestFocus(_colorFocus); }, onSaved: (title) => _formData['$title'] = title ?? '', ), TextFormField( decoration: const InputDecoration(labelText: 'Color'), textInputAction: TextInputAction.next, focusNode: _colorFocus, onFieldSubmitted: (_) { FocusScope.of(context).requestFocus(_iconFocus); }, onSaved: (color) => _formData['color'] = color ?? Colors.green, ), TextFormField( decoration: const InputDecoration(labelText: 'Icon'), textInputAction: TextInputAction.done, focusNode: _iconFocus, onFieldSubmitted: (_) => _submitForm(), onSaved: (icon) => _formData['icon'] = icon ?? Icons.save, ), ], )), ), ); } }
请问如何让程序识别并获取对应的Icon和Color类型值?
解决方案
当前代码的核心问题是:TextFormField的输入是字符串类型,直接存入_formData后强转Color/IconData会触发类型转换错误;另外Title字段的onSaved逻辑有误,键名写成了$title导致无法正确取值。
解决步骤
- 编写字符串转类型的工具函数:将输入的"Colors.red"、"Icons.save"这类字符串映射到对应的
Color和IconData实例 - 修正表单字段的
onSaved逻辑:调用转换函数处理输入字符串,将目标类型存入_formData - 修复Title字段的键名错误:把
_formData['$title']改为_formData['title']
修改后的表单页面代码
import 'package:apetit_project/models/satisfacao.dart'; import 'package:flutter/material.dart'; class SatisfactionFormScreen extends StatefulWidget { const SatisfactionFormScreen({Key? key}) : super(key: key); @override State<SatisfactionFormScreen> createState() => _SatisfactionFormScreenState(); } class _SatisfactionFormScreenState extends State<SatisfactionFormScreen> { final _titleFocus = FocusNode(); final _colorFocus = FocusNode(); final _iconFocus = FocusNode(); final _formKey = GlobalKey<FormState>(); final _formData = Map<String, Object>(); // 字符串转Color Color? _stringToColor(String? colorStr) { if (colorStr == null || colorStr.isEmpty) return null; // 提取Colors后面的属性名,比如"Colors.red"提取"red" final colorName = colorStr.split('.').last; switch (colorName) { case 'red': return Colors.red; case 'green': return Colors.green; case 'blue': return Colors.blue; case 'orange': return Colors.orange; // 可以继续添加更多需要支持的颜色 default: return Colors.orange; // 默认颜色 } } // 字符串转IconData IconData? _stringToIcon(String? iconStr) { if (iconStr == null || iconStr.isEmpty) return null; // 提取Icons后面的属性名,比如"Icons.save"提取"save" final iconName = iconStr.split('.').last; switch (iconName) { case 'save': return Icons.save; case 'delete': return Icons.delete; case 'edit': return Icons.edit; case 'add': return Icons.add; // 可以继续添加更多需要支持的图标 default: return Icons.save; // 默认图标 } } @override void dispose() { super.dispose(); _titleFocus.dispose(); _colorFocus.dispose(); _iconFocus.dispose(); // 释放未处理的FocusNode } void _submitForm() { if (!_formKey.currentState!.validate()) return; // 先验证表单合法性 _formKey.currentState?.save(); final newSatisfacao = Satisfacao( id: _formData['id'] as String, title: _formData['title'] as String, color: _formData['color'] as Color, icon: _formData['icon'] as IconData, ); print(newSatisfacao.id); print(newSatisfacao.title); print(newSatisfacao.color); print(newSatisfacao.icon); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Formulário de Satisfação'), actions: [ IconButton( onPressed: _submitForm, icon: const Icon(Icons.save), ), ], ), body: Padding( padding: const EdgeInsets.all(15), child: Form( key: _formKey, child: ListView( children: [ TextFormField( decoration: const InputDecoration(labelText: 'Id'), textInputAction: TextInputAction.next, onFieldSubmitted: (_) { FocusScope.of(context).requestFocus(_titleFocus); }, onSaved: (id) => _formData['id'] = id ?? '', validator: (value) { if (value == null || value.isEmpty) { return '请输入Id'; } return null; }, ), TextFormField( decoration: const InputDecoration(labelText: 'Title'), textInputAction: TextInputAction.next, focusNode: _titleFocus, onFieldSubmitted: (_) { FocusScope.of(context).requestFocus(_colorFocus); }, onSaved: (title) => _formData['title'] = title ?? '', // 修复键名错误 validator: (value) { if (value == null || value.isEmpty) { return '请输入Title'; } return null; }, ), TextFormField( decoration: const InputDecoration(labelText: 'Color'), textInputAction: TextInputAction.next, focusNode: _colorFocus, onFieldSubmitted: (_) { FocusScope.of(context).requestFocus(_iconFocus); }, onSaved: (colorStr) { final color = _stringToColor(colorStr); _formData['color'] = color ?? Colors.orange; }, ), TextFormField( decoration: const InputDecoration(labelText: 'Icon'), textInputAction: TextInputAction.done, focusNode: _iconFocus, onFieldSubmitted: (_) => _submitForm(), onSaved: (iconStr) { final icon = _stringToIcon(iconStr); _formData['icon'] = icon ?? Icons.save; }, ), ], )), ), ); } }
补充说明
- 转换函数通过
switch语句映射字符串到具体类型,可根据需求扩展更多颜色和图标的支持 - 新增表单验证逻辑,确保必填字段不为空
- 修复了
_iconFocus未释放的问题,避免内存泄漏
内容的提问来源于stack exchange,提问作者pedro.curti
相关产品推荐
相关产品推荐

