【问题标题】:DropDownButton: Adjust height of itemsDropDownButton:调整项目的高度
【发布时间】:2022-01-10 12:56:58
【问题描述】:

我有下拉按钮:

DropdownButtonHideUnderline(
    child: DropdownButton(
      isExpanded: true,
      value: value,
      items: widget.items.map((item) {
        return DropdownMenuItem(
          value: item, 
          child: Container(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start, 
              children: [
                Text(
                  item.toString(),
                ),
                Container(
                  child: Text(
                    item.subtitle.toString(),
                    maxLines: 2,
                    overflow: TextOverflow.ellipsis,
                  ),
                  padding: EdgeInsets.only(left: 10.0)
                ),
              ]),
              padding: EdgeInsets.only(bottom: 10),
            )
      }).toList(),
      onChanged: widget.onChanged,
      selectedItemBuilder: (context) {
        return widget.items.map((item) {
          return Align(
            child: Text(
              item.toString(),
            ),
            alignment: Alignment.centerLeft,
          );
        }).toList();
      }
    )
  )

我正在尝试实现一个标题和一个副标题(更小的描述)。标题正在生成“按钮溢出”,字幕溢出到下一项。

是否有机会根据其内容所需的空间调整高度?

编辑:

Example: DartPad

编辑:

为了更清楚:我的目标是允许:

  • 至少一行标题,可以允许两行标题
  • 可选最多两行字幕

每个项目制作 1-4 行。列表中项目的高度应根据其内容进行调整。

【问题讨论】:

  • 请提供一个简单的可运行代码。谢谢。
  • 请参阅我的答案以获取长下拉列表herehere 希望对您有所帮助。或者将您的列小部件放入SingleChildScollView() 参考here
  • @RavindraS.Patil 我看不出你的例子对我有什么帮助,对不起。 DropDown 本身就像魅力一样。对我来说,项目元素中的第二个文本元素是问题所在。它不调整高度。您的示例的哪一部分解决了这个问题?
  • 能否提供项目列表,以便运行检查
  • 如果你显示标题和副标题那么使用 ListTile 小部件

标签: flutter drop-down-menu


【解决方案1】:

您可以使用DropdownButton2 更改下拉项目的高度。使用 itemHeight 属性来做到这一点。

【讨论】:

  • 虽然我真的不想为这样的核心功能使用外部依赖项,但您能否提供一个 itemHeight 依赖于其小部件的示例。有时标题是单行的,有时更多。字幕有时存在,有时不存在....
  • 我不喜欢使用太多的外部依赖,但我发现 DropdownButton 缺少很多功能,所以我制作了那个包。它与 Flutter 的核心 DropdownButton 相同,但可定制性更高,因此具有相同的性能。
  • 对于会影响下拉列表性能的动态 itemHeight 可以容纳长列表。 Flutter 的 DropdownButton 将高度硬编码为 _kMenuItemHeight。虽然我已经选择使用 itemHeight 属性来更改高度,但我还添加了一个选项来为分隔线之类的东西添加辅助不同的高度。您可以将它用于带有字幕的项目,以赋予它们不同的高度。请参阅包含添加不同高度分隔线的包的示例。
  • 好的,我明白了。但这不是我真正需要的。我需要放入任何类型的小部件(在我的示例中是带有两个文本小部件的列),并且需要根据小部件大小拉伸高度。正如在列表或任何其他地方完成的那样......我的问题是,我事先不知道行数。这取决于本地化等。我不能说:CustomHeight = X。对于某些语言,X 可能会变得太大,而对于某些语言,X 可能会变得太小。我希望看到更灵活的解决方案。你相信,有可能吗?
  • 您可以制作自己的自定义下拉菜单来实现这一点,但我不确定这是否会提高性能。另一种解决方案是让某些 x 行的 Height 稍微大一些,并给出描述 maxLines 值和 TextOverflow.ellipsis。
【解决方案2】:

请检查:

import 'package:flutter/material.dart';

void main() {
  runApp(Nav2App());
}

class Nav2App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
    home: HomeScreen(),
    );
  }
}

class HomeScreen extends StatefulWidget {
  @override
  State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  String? sid;
  List data = [{"nome":"Acura Acura Acura Acura ","codigo":"1 2 3 4 5 6 7 8 9 10 11 12 1"},
               {"nome":"Agrale Agrale","codigo":" 8 9 10 11 12 1 2 3 4 5 6 7 8 9 10 11 12 1 2 3 4 5 6 "}
              ];
  
  
  PageController _scrollController = PageController();
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
    children: <Widget>[
      Expanded(
        child: Container(
          width: 200,
          child: InputDecorator(
            decoration: InputDecoration(
              border: OutlineInputBorder(),
            ),
            child: DropdownButtonHideUnderline(
              child: DropdownButton(
                isDense: true,
                isExpanded: true,
                value: sid,
                hint: Text("Select Data",
                    style: TextStyle(color: Colors.black)),
                items: data.map((item) {
                  return DropdownMenuItem(
                    child: Container(
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.start, 
                        mainAxisSize: MainAxisSize.min,
                        children: [
                          Text(
                            item['nome'].toString(),
                          ),
                          Flexible( child:Container(
                            child:  Text(
                              item['codigo'].toString(),
                              maxLines: 2,
                              overflow: TextOverflow.ellipsis,
                            ),
                            padding: EdgeInsets.only(left: 10.0)
                          ),),
                        ]),
                        padding: EdgeInsets.only(bottom: 10),
                      ),
                    value: item['codigo'].toString(),
                  );
                }).toList(),
                onChanged: (value) {
                  setState(() {
                    sid = value as String?;
                  });
                },
              ),
            ),
          ),
        ),
      ),
    ],
  ),
      
    );
  }
}

只需将 Column 中的第二个 Container 包装为带有 Flexible 小部件的字幕。

编辑: 对于多行标题和副标题:

import 'package:flutter/material.dart';

void main() {
  runApp(Nav2App());
}

class Nav2App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: HomeScreen(),
    );
  }
}

class HomeScreen extends StatefulWidget {
  @override
  State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  String? sid;
  List data = [
    {
      "nome": "Acura Acura Acura Acura Acura Acura Acura",
      "codigo": "1 2 3 4 5 7 8 9 10 12 76 7 8 9 22 23 34 45"
    },
    {
      "nome": "Agrale Agrale",
      "codigo": " 8 9 10 11 12 2 23 34 56 78 90 11 12 34"
    }
  ];

  PageController _scrollController = PageController();
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        mainAxisSize: MainAxisSize.min,
        mainAxisAlignment: MainAxisAlignment.start,
        children: <Widget>[
          Container(
            width: 250,
            child: InputDecorator(
              decoration: InputDecoration(
                border: OutlineInputBorder(),
              ),
              child: DropdownButtonHideUnderline(
                child: DropdownButton(
                  itemHeight: 70,
                  isExpanded: true,
                  isDense: true,
                  value: sid,
                  hint: Text("Select Data",
                      style: TextStyle(color: Colors.black)),
                  items: data.map((item) {
                    return DropdownMenuItem(
                      child: Column(
                        mainAxisAlignment: MainAxisAlignment.start,
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          Flexible(
                            child: Text(
                              item['nome'].toString(),
                              maxLines: 2,
                              overflow: TextOverflow.ellipsis,
                            ),
                          ),
                          Flexible(
                            child: Text(
                              item['codigo'].toString(),
                              maxLines: 2,
                              overflow: TextOverflow.ellipsis,
                            ),
                          ),
                        ],
                      ),
                      value: item['codigo'].toString(),
                    );
                  }).toList(),
                  onChanged: (value) {
                    setState(() {
                      sid = value as String?;
                    });
                  },
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

让我知道它是否适合你。

【讨论】:

  • 我也试过了,但正如你所见,我再也没有换行了。我的目标是允许至少 2 行标题和副标题。
  • @S-Man : 请用编辑标签检查我的答案。希望这会对你有所帮助。
  • 感谢您指出 itemHeight。我想,这将是最好的解决方法,但不是我希望的最终解决方案。似乎不可能获得灵活的项目高度,不是吗(请参阅第二个示例中的空行,我想避免它......)。感谢您的努力!
【解决方案3】:

试试下面的代码希望它对你有帮助。参考 ListTile here

String? sid;
  List data = [];
  var urls = "https://parallelum.com.br/fipe/api/v1/carros/marcas";

您的 API 调用函数:

Future fetchData() async {
    var result = await http.get(Uri.parse(urls), headers: {
      'Content-Type': 'application/json',
      'Accept': 'application/json',
    });
    var jsonData = json.decode(result.body);

    setState(() {
      data = jsonData;
    });
    return jsonData;
  }

在 initState() 中调用您的 API fetchData()

@override
  void initState() {
    fetchData();
    super.initState();
  }

您的下拉小部件:

Container(
    margin: EdgeInsets.all(20),
    width: 200,
    height: 70,
    decoration: BoxDecoration(
      border: Border.all(),
      borderRadius: BorderRadius.circular(
        20,
      ),
    ),
    child: DropdownButtonHideUnderline(
      child: DropdownButton(
        isDense: true,
        isExpanded: true,
        value: sid,
        hint: Padding(
          padding: const EdgeInsets.all(8.0),
          child: Text(
            "Select Data",
            style: TextStyle(
              color: Colors.black,
            ),
          ),
        ),
        items: data.map((list) {
          return DropdownMenuItem(
            child: ListTile(
              title: Text(list['nome']),
              subtitle: Text(list['nome']),
            ),  
            value: list['codigo'].toString(),
          );
        }).toList(),
        onChanged: (value) {
          setState(() {
            sid = value as String?;
          });
        },
      ),
    ),
  ),

下拉按钮的结果屏幕 ->

下拉列表的结果屏幕->

选择下拉项后的结果屏幕->

【讨论】:

  • 不幸的是,它对我不起作用:i.stack.imgur.com/TvdCA.png 它只消除了“底部溢出”错误,但重叠仍然存在。 (顺便说一句:将“副标题”更改为“副标题”)
  • 你能分享你的网址吗?
  • 当然可以,但是不知道有没有用,因为这是个大工程...github.com/S-Man42/GCWizard/blob/2.2.0/lib/widgets/common/base/…
  • @S-Man 检查我的更新答案我使用了虚拟数据
  • 抱歉,还是没有效果。我在代码中看到的唯一区别是isDense: true。但这没有什么区别。如果文本较长并导致换行,您的代码是否仍然有效?
猜你喜欢
  • 2021-07-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-01
  • 2021-04-02
相关资源
最近更新 更多