【问题标题】:Flutter Dropdown Button and Dropdown Handler different sizeFlutter Dropdown Button和Dropdown Handler不同大小
【发布时间】:2022-02-03 03:42:49
【问题描述】:

我想在颤振上创建一个下拉菜单,其中打开下拉菜单的处理程序按钮仅使用一个图标,而由它打开的菜单列表使用一个图标和一个文本。

我几乎设法创建了它,您可以查看以下屏幕截图:

Closed Opened

我正在为打开的宽度而苦苦挣扎,所以我的问题是如何为打开的菜单提供足够的宽度并将处理程序按钮保持在其当前宽度。

请注意,我希望下拉列表位于行的末尾,因此请将此黑框视为其他区域,并不重要。

我将在下面添加相关代码,并在以下链接中添加完整代码。

import 'package:flutter/material.dart';
import 'package:rxdart/rxdart.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({
    Key? key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "Question Dropdown",
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: HomePage(
        optionStream: BehaviorSubject<Option>(),
      ),
    );
  }
}

class HomePage extends StatelessWidget {
  final BehaviorSubject<Option> optionStream;

  const HomePage({
    Key? key,
    required this.optionStream,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("Question Dropdown"),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Row(
              children: [
                Expanded(
                  child: Container(
                    height: 48,
                    color: Colors.black,
                  ),
                ),
                Padding(
                  padding: const EdgeInsets.all(16.0),
                  child: StreamBuilder<Option>(
                    initialData: Option.A,
                    stream: optionStream,
                    builder: (context, snapshot) {
                      final option = snapshot.data ?? Option.A;
                      return _dropDownMenu(context, option);
                    },
                  ),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }

  Widget _dropDownMenu(
    BuildContext context,
    Option option,
  ) {
    const items = Option.values;
    return DropdownButtonHideUnderline(
      child: DropdownButton<Option>(
        value: option,
        selectedItemBuilder: (context) =>
            items.map((e) => _dropdownHandler(context, e)).toList(),
        items: items.map((e) => _dropdownItem(context, e)).toList(),
        onChanged: (e) => optionStream.add(e ?? Option.A),
      ),
    );
  }

  OptionsItemHelper _dropDownItemData(
    BuildContext context,
    Option option,
  ) {
    Widget icon;
    String text;
    switch (option) {
      case Option.A:
        icon = const Icon(Icons.ac_unit);
        text = "An option";
        break;
      case Option.B:
        icon = const Icon(Icons.baby_changing_station);
        text = "Best option";
        break;
      case Option.C:
        icon = const Icon(Icons.cake_sharp);
        text = "Closest option";
        break;
      case Option.D:
        icon = const Icon(Icons.dashboard);
        text = "Dumb option";
        break;
    }
    return OptionsItemHelper(text, icon);
  }

  Widget _dropdownHandler(
    BuildContext context,
    Option option,
  ) {
    final helper = _dropDownItemData(context, option);
    return helper.icon;
  }

  DropdownMenuItem<Option> _dropdownItem(
    BuildContext context,
    Option option,
  ) {
    final helper = _dropDownItemData(context, option);
    return DropdownMenuItem<Option>(
      value: option,
      child: Row(
        children: [
          helper.icon,
          const SizedBox(width: 16),
          Text(helper.text),
        ],
      ),
    );
  }
}

enum Option {
  A,
  B,
  C,
  D,
}

class OptionsItemHelper {
  final String text;
  final Widget icon;

  OptionsItemHelper(
    this.text,
    this.icon,
  );
}

Complete code on Github

Complete code on Gitlab

【问题讨论】:

标签: flutter drop-down-menu width dropdown


【解决方案1】:

我确实找到了使用 GestureDetector 和 showMenu 的解决方法,我在这里分享并推送到 repo 作为“解决方法”提交,以防您需要与我现在需要的相同,我将保留问题而没有答案以防有人使用下拉菜单找到更好的方法。

新的下拉菜单功能

  Widget _dropDownMenu(
    BuildContext context,
    Option option,
  ) {
    const items = Option.values;
    return GestureDetector(
      onTapDown: (details) async {
        final offset = details.globalPosition;
        final newOption = await showMenu(
          context: context,
          position: RelativeRect.fromLTRB(offset.dx, offset.dy, 0, 0),
          items: items.map((e) => _dropdownItem(context, e, option)).toList(),
        );
        if (newOption != null) {
          optionStream.add(newOption);
        }
      },
      child: _dropdownHandler(context, option),
    );
  }

还有新的 dropdownItem 函数。

  PopupMenuEntry<Option> _dropdownItem(
    BuildContext context,
    Option option,
    Option selected,
  ) {
    final helper = _dropDownItemData(context, option);
    return CheckedPopupMenuItem<Option>(
      value: option,
      checked: option == selected,
      child: Row(
        children: [
          Expanded(child: Container()),
          Text(helper.text),
          const SizedBox(width: 16),
          helper.icon,
        ],
      ),
    );
  }

它的样子

Closed Opened Bigger Screen

【讨论】:

    猜你喜欢
    • 2020-09-19
    • 2021-12-21
    • 1970-01-01
    • 2021-01-20
    • 2012-06-07
    • 2021-12-20
    • 1970-01-01
    • 1970-01-01
    • 2016-01-05
    相关资源
    最近更新 更多