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

Flutter自定义图片Dropdown组件:文本溢出与显示异常求助

解决方案

要实现展开显示完整布局、收起仅显示图片+首行文本,同时解决文本溢出问题,核心是区分选中项与下拉项的布局,并正确处理文本的约束。以下是简洁的实现方式:

关键修改点

  • 用selectedItemBuilder自定义选中后的显示样式,只渲染图片和第一行文本
  • 给下拉项的文本列添加宽度约束,配合TextOverflow.ellipsis和maxLines处理长文本溢出
  • 避免在build方法中直接修改传入的items(会导致重复添加项的bug),而是创建新列表

修改后的完整代码

class BDImageDropdownButton extends StatelessWidget {
  final bool disabled;
  final String? labelText;
  final IconData? icon;
  final String? Function(dynamic)? validator;
  final FormFieldSetter<dynamic>? onSaved;
  final List<DropdownMenuItem<dynamic>> items;
  final dynamic value;
  final void Function(dynamic value)? onChanged;

  const BDImageDropdownButton({
    required this.labelText,
    this.icon,
    this.disabled = false,
    this.onChanged,
    this.validator,
    this.onSaved,
    required this.items,
    this.value,
    Key? key,
  }) : super(key: key);

  // 构建选中项的显示布局(仅图片+首行文本)
  Widget _buildSelectedItem(BuildContext context, dynamic itemValue) {
    // 实际项目中可根据选中的value对应数据获取文本,示例用固定文本演示
    return Row(
      children: [
        Image.asset('assets/radiatorTypes/testImage.png', height: 40),
        const SizedBox(width: 10),
        Expanded(
          child: Text(
            'Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium',
            style: Theme.of(context).textTheme.headline6?.copyWith(fontWeight: FontWeight.bold),
            overflow: TextOverflow.ellipsis,
            maxLines: 1,
          ),
        ),
      ],
    );
  }

  // 构建下拉项的完整布局(图片+三行文本)
  Widget _buildDropdownItem(BuildContext context) {
    return SizedBox(
      height: 100.0,
      child: Row(
        crossAxisAlignment: CrossAxisAlignment.center,
        children: <Widget>[
          Image.asset('assets/radiatorTypes/testImage.png', height: 60),
          const SizedBox(width: 10),
          Expanded( // 约束文本列宽度,避免溢出父容器
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(
                  'Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium',
                  style: Theme.of(context).textTheme.headline6?.copyWith(fontWeight: FontWeight.bold),
                  overflow: TextOverflow.ellipsis,
                  maxLines: 1,
                ),
                const SizedBox(height: 5),
                Text(
                  'odit aut fugit, sed quia consequuntur magni dolores eos qui ratione',
                  overflow: TextOverflow.ellipsis,
                  maxLines: 1,
                ),
                const SizedBox(height: 5),
                Text(
                  'iquid ex ea commodi consequatur? Quis autem vel eum',
                  overflow: TextOverflow.ellipsis,
                  maxLines: 1,
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    // 创建新列表添加示例项,避免修改原items导致重复添加
    final dropdownItems = List<DropdownMenuItem<dynamic>>.from(items)
      ..add(DropdownMenuItem(
        value: 1,
        child: _buildDropdownItem(context),
      ));

    return DropdownButtonFormField<dynamic>(
      validator: validator,
      decoration: InputDecoration(
        filled: true,
        prefixIcon: icon != null ? Icon(icon) : null,
        labelText: labelText,
        labelStyle: TextStyle(color: disabled ? Colors.grey : const Color(0xFFAFAFAF)),
        contentPadding: const EdgeInsets.only(left: 12, top: 9, bottom: 6, right: 12),
        errorBorder: const UnderlineInputBorder(
          borderSide: BorderSide(
            color: Color(0xffba0000),
            width: 3,
          ),
        ),
      ),
      items: disabled ? [] : dropdownItems,
      onChanged: onChanged,
      onSaved: onSaved,
      value: value,
      // 自定义选中项的显示样式
      selectedItemBuilder: (BuildContext context) {
        return dropdownItems.map((item) {
          return _buildSelectedItem(context, item.value);
        }).toList();
      },
    );
  }
}

额外说明

  1. 文本溢出处理:所有文本用Expanded约束宽度,配合maxLines:1和TextOverflow.ellipsis,确保长文本自动截断并显示省略号,视觉效果比fade更清晰。
  2. 布局分离:通过selectedItemBuilder完全控制选中后的显示内容,和下拉项布局彻底分离,解决了收起时显示全部三行的问题。
  3. 避免重复项bug:用List.from(items)创建新列表再添加示例项,防止每次build触发时重复添加下拉项。

内容的提问来源于stack exchange,提问作者Farsen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 13:15:24