如何在自定义Button类中使用FlutterIcon生成的自定义图标?
在Flutter自定义按钮组件中正确使用自定义图标
问题描述
我通过FlutterIcon工具生成了自定义图标类CustomIcons及对应的.ttf字体文件,希望在自定义LabelButton组件类中使用这些自定义图标。当将label!.uiIcon的值改为自定义图标相关名称时,代码可正常编译,但在手机端运行时出现**Bad state: No element.**错误,请问如何在自定义按钮类中正确使用自定义图标?
自定义图标类代码
import 'package:flutter/widgets.dart'; class CustomIcons { CustomIcons._(); static const _kFontFam = 'CustomIcons'; static const String? _kFontPkg = null; static const IconData construction = IconData(0xe841, fontFamily: _kFontFam, fontPackage: _kFontPkg); }
LabelButton组件代码
import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:my_package/custom_icons_icons.dart'; import '../utils/definitions.dart'; import 'icons.dart'; import '../model/label.dart'; class LabelButton extends StatelessWidget { final Label? label; final VoidStringCallback? process; LabelButton({required this.label, required this.process, Key? key}) : super(key: key); @override Widget build(BuildContext context) { if (label != null) { return Padding( padding: const EdgeInsets.all(8.0), child: ClipRRect( borderRadius: BorderRadius.circular(12), child: Material( child: InkWell( highlightColor: Color(0xFF00D3F8).withOpacity(0.3), splashColor: Color(0xFFB20DD3).withOpacity(0.3), onTap: () { process!(label!.name); HapticFeedback.lightImpact(); }, child: Ink( width: 100, // 调整宽度 height: 120, // 调整高度 decoration: BoxDecoration( color: Color(0xFFB6B6B6), ), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Icon(iconList .firstWhere((element) => element.name == label!.uiIcon) .icon, size: 80,), Icon(CustomIcons.construction, size: 80,), Text(label!.categoryName, style: const TextStyle( color: Color(0xFF696969), )), Text(label!.name, style: const TextStyle( fontWeight: FontWeight.bold, )), // 图标下方文字 ], ), ), ), ) ) ); } else { return Container(); } } const LabelButton._(this.label, this.process, {Key? key}) : super(key: key); static LabelButton createBlank() { return const LabelButton._(null, null); } }
图标列表代码
import 'package:flutter/material.dart'; class Category { String name; IconData icon; Category(this.name, this.icon); } List<Category> iconList = [ Category("construction", Icons.man), Category("bicycle", Icons.pedal_bike), Category("motorcycle", Icons.motorcycle), Category("car", Icons.car_rental), Category("train", Icons.train), Category("stroller", Icons.stroller), Category("rain", Icons.water_drop), Category("snow", Icons.snowing), Category("fog", Icons.foggy), Category("street_light", Icons.traffic), Category("street_sign", Icons.signpost), Category("star", Icons.star) ];
解决方案
错误原因
Bad state: No element. 错误的核心原因是:当你修改label!.uiIcon为自定义图标名称后,iconList中没有对应的Category条目,firstWhere方法找不到匹配元素时会抛出异常。
具体解决步骤
更新图标列表,关联自定义图标
修改iconList中的对应条目,将原有的系统图标替换为自定义图标:List<Category> iconList = [ Category("construction", CustomIcons.construction), // 替换Icons.man为自定义图标 Category("bicycle", Icons.pedal_bike), Category("motorcycle", Icons.motorcycle), // 保留其他原有条目 ];添加异常兜底处理(推荐)
为了避免后续因图标名称不匹配导致崩溃,给firstWhere添加orElse回调,返回默认图标作为兜底:Icon( iconList.firstWhere( (element) => element.name == label!.uiIcon, orElse: () => Category("default", Icons.error_outline), // 无匹配时返回默认错误图标 ).icon, size: 80, ),确认字体文件配置正确
确保.ttf字体文件已在pubspec.yaml中正确配置,路径需与实际文件位置一致:flutter: fonts: - family: CustomIcons fonts: - asset: fonts/CustomIcons.ttf # 示例路径,根据你的实际位置修改直接映射自定义图标(替代方案)
如果不想通过iconList中转,也可以通过条件判断直接返回对应图标:// 在LabelButton类中添加方法 IconData getTargetIcon() { switch(label!.uiIcon) { case "construction": return CustomIcons.construction; case "bicycle": return Icons.pedal_bike; // 其他图标映射 default: return Icons.error_outline; } } // 在build方法中使用 Icon(getTargetIcon(), size: 80),
内容的提问来源于stack exchange,提问作者Test
相关产品推荐
相关产品推荐

