【问题标题】:Flutter: Close DropdownButton (DropdownMenu)Flutter:关闭下拉按钮(DropdownMenu)
【发布时间】:2021-07-30 01:02:39
【问题描述】:

有没有办法在执行 onTap 函数时关闭包含所有 DropdownMenuItems 的 DropdownButton 的选择菜单(DropdownMenuItem 中的 GestureDetector)?

这是我对 Alperen Baskaya 方法的实现(略微简化的版本以便于理解)。但是,这种方法还不起作用,我不确定是因为我实施不正确还是因为该方法不适用于我的问题。

class _BoatSelectionState extends State<BoatSelection> {
  FocusNode focusNode;
  
  @override
  void initState() {
    super.initState();
    focusNode = FocusNode();
  }

  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        Expanded(
          child: 
            DropdownButtonHideUnderline(
              child: DropdownButton<Boat>(
                focusNode: focusNode,
                icon: Icon(
                  Icons.keyboard_arrow_down_rounded,
                  color: Colors.black,
                ),
                isExpanded: true,
                value: selectedBoat,
                onChanged: (Boat _boat) => Provider.of<BoatStreamsCubit>(context, listen: false).setBoat(_boat),
                selectedItemBuilder: (BuildContext context) {
                  return widget.boats.map<Widget>((Boat boat) {
                    return Row(
                      mainAxisAlignment: MainAxisAlignment.center,
                      crossAxisAlignment: CrossAxisAlignment.center,
                      children: [
                        BoatClassLogo(boat: boat),
                        Expanded(
                          child: Padding(
                            padding: const EdgeInsets.only(left: DesignValues.paddingMd),
                            child: BoatInformation(boat: boat),
                          ),
                        ),
                      ],
                    );
                  }).toList();
                },
                items: widget.boats.map<DropdownMenuItem<Boat>>((Boat _boat) {
                  return DropdownMenuItem<Boat>(
                    value: _boat,
                    child: Row(
                      crossAxisAlignment: CrossAxisAlignment.center,
                      children: [
                        Padding(
                          padding: const EdgeInsets.only(right: DesignValues.paddingMd),
                          child: BoatClassLogo(boat: _boat),
                        ),
                        Expanded(
                          child: BoatInformation(boat: _boat),
                        ),
                        GestureDetector(
                          onTap: () {
                            focusNode.unfocus();
                            Navigator.push(context, MaterialPageRoute(builder: (context) => BoatForm(CreationState.edit, _boat)));
                          },
                          child: Padding(
                            padding: const EdgeInsets.symmetric(horizontal: 5.0),
                            child: Icon(
                              Icons.edit,
                              color: AppColors.primary,
                            ),
                          ),
                        ),
                      ],
                    ),
                  );
                }).toList(),
              ),
          ),
        ),
      ],
    );
  }
}

【问题讨论】:

    标签: flutter dropdownbutton flutter-dropdownbutton


    【解决方案1】:

    我查看了 dart 中下拉菜单的内部实现。下拉列表的弹出框是使用 Navigator.push() 创建的。它等待用户单击一个项目并使用 Navigator.pop() 返回值。所以我们可以通过全局键获取下拉菜单的上下文来手动弹出弹出框。

    void initState() {
        super.initState();
        dropdownKey = GlobalKey();
    }
    

    ...

    DropdownButton<Boat>(
        key: dropdownKey,
    

    ...

    GestureDetector(
        onTap: () {
            Navigator.pop(dropdownKey.currentContext);
    

    完整代码:

    class _BoatSelectionState extends State<BoatSelection> {
      GlobalKey dropdownKey;
      
      @override
      void initState() {
        super.initState();
        dropdownKey = GlobalKey(); // Init GlobalKey, allows to close the DropdownButton
      }
    
      @override
      Widget build(BuildContext context) {
        return Row(
          children: [
            Expanded(
              child: 
                DropdownButtonHideUnderline(
                  child: DropdownButton<Boat>(
                    key: dropdownKey,
                    icon: Icon(
                      Icons.keyboard_arrow_down_rounded,
                      color: Colors.black,
                    ),
                    isExpanded: true,
                    value: selectedBoat,
                    onChanged: (Boat _boat) => Provider.of<BoatStreamsCubit>(context, listen: false).setBoat(_boat),
                    selectedItemBuilder: (BuildContext context) {
                      return widget.boats.map<Widget>((Boat boat) {
                        return Row(
                          mainAxisAlignment: MainAxisAlignment.center,
                          crossAxisAlignment: CrossAxisAlignment.center,
                          children: [
                            BoatClassLogo(boat: boat),
                            Expanded(
                              child: Padding(
                                padding: const EdgeInsets.only(left: DesignValues.paddingMd),
                                child: BoatInformation(boat: boat),
                              ),
                            ),
                          ],
                        );
                      }).toList();
                    },
                    items: widget.boats.map<DropdownMenuItem<Boat>>((Boat _boat) {
                      return DropdownMenuItem<Boat>(
                        value: _boat,
                        child: Row(
                          crossAxisAlignment: CrossAxisAlignment.center,
                          children: [
                            Padding(
                              padding: const EdgeInsets.only(right: DesignValues.paddingMd),
                              child: BoatClassLogo(boat: _boat),
                            ),
                            Expanded(
                              child: BoatInformation(boat: _boat),
                            ),
                            GestureDetector(
                              onTap: () {
                                Navigator.pop(dropdownKey.currentContext); // Closes the dropdown
                                Navigator.push(context, MaterialPageRoute(builder: (context) => BoatForm(CreationState.edit, _boat)));
                              },
                              child: Padding(
                                padding: const EdgeInsets.symmetric(horizontal: 5.0),
                                child: Icon(
                                  Icons.edit,
                                  color: AppColors.primary,
                                ),
                              ),
                            ),
                          ],
                        ),
                      );
                    }).toList(),
                  ),
              ),
            ),
          ],
        );
      }
    }
    

    【讨论】:

      【解决方案2】:

      如果我没听错,您可以使用焦点节点作为下拉菜单。

      FocusNode dropdown;
      

      需要在initstate中初始化;

      dropdown = FocusNode();
      
      child: DropdownButtonHideUnderline(
                               child: DropdownButton <String>(
                                  focusNode: dropdown,
      

      那么当你想关闭这个菜单时,在 ontap 中执行;

        dropdown.unfocus();
      

      【讨论】:

      • 感谢您的回答。该建议本身看起来很有希望,但不幸的是 unfocus() 没有效果并且不会改变我的问题。这是我在略微简化的版本中的实现,以便可以理解:Pastebin。是我在实施过程中做错了什么还是该方法不起作用?
      • 我看不到您在 Pastbin 链接下粘贴的内容。当我使用 unfocus 功能时,下拉列表消失。但是您可以在 onTap 函数中使用 setState() 再次构建您的主窗口小部件。它可能会有所帮助。如果你粘贴你的代码,我可以正确地看到错误是什么
      • 你试过用 setState 包裹 unfocus 和 navigator 吗?
      • setState(() { focusNode.unfocus(); Navigator.push( context, MaterialPageRoute( builder: (context) =&gt; BoatForm(CreationState.edit, _boat), ), ); }); 不幸的是,这并没有改变任何东西。
      猜你喜欢
      • 2020-11-10
      • 1970-01-01
      • 2022-10-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-28
      相关资源
      最近更新 更多