0

有没有办法在执行 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(),
              ),
          ),
        ),
      ],
    );
  }
}
4

2 回答 2

2

我在 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(),
              ),
          ),
        ),
      ],
    );
  }
}
于 2021-05-12T10:01:50.660 回答
1

如果我说对了,您可以将焦点节点用于下拉菜单。

FocusNode dropdown;

需要在 initstate 中初始化;

dropdown = FocusNode();

child: DropdownButtonHideUnderline(
                         child: DropdownButton <String>(
                            focusNode: dropdown,

然后,当您可能想关闭此菜单时,请在 ontap 中执行;

  dropdown.unfocus();
于 2021-05-07T20:52:24.247 回答