You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在自定义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方法找不到匹配元素时会抛出异常。

具体解决步骤

  1. 更新图标列表,关联自定义图标
    修改iconList中的对应条目,将原有的系统图标替换为自定义图标:

    List<Category> iconList = [
      Category("construction", CustomIcons.construction), // 替换Icons.man为自定义图标
      Category("bicycle", Icons.pedal_bike),
      Category("motorcycle", Icons.motorcycle),
      // 保留其他原有条目
    ];
    
  2. 添加异常兜底处理(推荐)
    为了避免后续因图标名称不匹配导致崩溃,给firstWhere添加orElse回调,返回默认图标作为兜底:

    Icon(
      iconList.firstWhere(
        (element) => element.name == label!.uiIcon,
        orElse: () => Category("default", Icons.error_outline), // 无匹配时返回默认错误图标
      ).icon,
      size: 80,
    ),
    
  3. 确认字体文件配置正确
    确保.ttf字体文件已在pubspec.yaml中正确配置,路径需与实际文件位置一致:

    flutter:
      fonts:
        - family: CustomIcons
          fonts:
            - asset: fonts/CustomIcons.ttf # 示例路径,根据你的实际位置修改
    
  4. 直接映射自定义图标(替代方案)
    如果不想通过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 04:33:11