【问题标题】:Custom Widget not Rendering自定义小部件未呈现
【发布时间】:2021-12-02 10:40:44
【问题描述】:

我做了一个自定义的下拉选择器,问题是当我切换它时,小部件没有被渲染

用户界面上有 2 个下拉菜单。在不同的情况下,子下拉菜单可能可见也可能不可见。

只有当我同时有父下拉菜单和子下拉菜单时才会出现问题,并且在下一种情况下,这两个下拉菜单都是可见的。

这些是我的动态 UI 如何呈现的以下案例

案例1)UI上的DropDown1和Drop DropDown2(Drop Down 2是父widget)

当用户点击下拉 2 项时,主 UI 被渲染。

(下拉 2 项分钟、小时、日、周) DropDown 1 项根据下拉 2 更改)

class CustomDropDown extends StatefulWidget {
  final List<String> dropDownList;
  final defaultVal;
  final Function selectedItem;
  final customDropDownId;
  final isExpanded;
  final dropDownType;

  const CustomDropDown(
      {Key? key,
      required this.dropDownList,
      required this.defaultVal,
      required this.selectedItem,
      this.customDropDownId,
      this.isExpanded = false,
      required this.dropDownType})
      : super(key: key);

  @override
  _CustomDropDownState createState() => _CustomDropDownState();
}

class _CustomDropDownState extends State<CustomDropDown> {

  var chosenValue;

  @override
  void initState() {
    super.initState();
    print("initState");
    chosenValue = widget.defaultVal;

  }


  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    print("didChangeDependencies");
  }



  @override
  void dispose() {
    super.dispose();
    print("dispose");
  }

  @override
  Widget build(BuildContext context) {
    ThemeData themeData = Theme.of(context);
    print("dropDownList ${widget.dropDownList}  defaultVal ${widget.defaultVal}  chosenValue ${chosenValue} ");

    if (widget.dropDownType == DropDownType.DROPDOWN_WITH_ARROW) {
      return Material(
        elevation: 10,
        color: foreground_color,
        borderRadius: BorderRadius.circular(10.r),
        child: Padding(
          padding: EdgeInsets.symmetric(horizontal: 5.w),
          child: DropdownButton<String>(
            value: chosenValue,
            isExpanded: widget.isExpanded,
            dropdownColor: foreground_color,
            icon: const Icon(Icons.keyboard_arrow_down_rounded),
            borderRadius: BorderRadius.circular(10.r),
            underline: const SizedBox(),
            style: const TextStyle(color: Colors.white),
            iconEnabledColor: Colors.white,
            items: widget.dropDownList
                .map<DropdownMenuItem<String>>((String value) {
              return DropdownMenuItem<String>(
                value: value,
                child: Text(
                  value,
                  style: const TextStyle(color: Colors.white),
                ),
              );
            }).toList(),
            onChanged: (String? value) {
              if (value != null) {
                setState(() {
                  chosenValue = value;
                  widget.selectedItem(chosenValue, widget.customDropDownId);
                });
              }
            },
          ),
        ),
      );
    } 

父小部件

  Widget repeatEveryWidget(chosenValue) {
    if (chosenValue == dropDownJobList[0] ||
        chosenValue == dropDownJobList[1]) {
      bool isMinutesWidget = chosenValue == dropDownJobList[0];
      List<String> dropDownList = isMinutesWidget ? minutesList : hourList;

      return CustomDropDown(
        isExpanded: false,
        dropDownList: dropDownList,
        defaultVal:
            isMinutesWidget ? defaultMinuteSelected : defaulHourSelected,
        dropDownType: DropDownType.DROPDOWN_WITH_ARROW,
        selectedItem: (String selectedVal, DropDownsType dropDownId) {
          if (isMinutesWidget) {
            defaultMinuteSelected = selectedVal;
          } else {
            defaulHourSelected = selectedVal;
          }
        },
        customDropDownId: DropDownsType.CustomId,
      );
    } else {
      return const SizedBox();
    }
  }

家长电话

Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      Row(
                        children: [
                          const Text(REPEAT_EVERY),
                          SizedBox(
                            width: 10.w,
                          ),
                          repeatEveryWidget(chosenValue),
                          SizedBox(
                            width: 10.w,
                          ),
                          CustomDropDown(
                            dropDownList: dropDownCustomList,
                            defaultVal: chosenValue,
                            dropDownType: DropDownType.DROPDOWN_WITH_ARROW,
                            selectedItem:
                                (String selectedVal, DropDownsType dropDownId) {
                              setState(() {
                                chosenValue = selectedVal;
                              });
                            },
                            customDropDownId:
                                DropDownsTypeRepeatPicker,
                          ),
                        ],
                      ),

)

输出

如果用户选择项目 1 分钟,然后选择除小时以外的任何项目,则子下拉菜单将从 UI 中删除。但是,当用户在一分钟后选择几小时后,Items in Child 小部件会呈现,但它的 defaultValue 不会选择新值,它会保留在几分钟内选择的旧数据,因为 UI 尚未被破坏。

【问题讨论】:

    标签: flutter dart widget dropdown


    【解决方案1】:

    上述问题的答案在于扑朔迷离的语句管理。 因为有两个具有字符串对象的列表,并且某些数据相同,例如“5”,“10”

    const List<String> minutesListConfig = ['5', '10', '15', '30', '45', '60'];
    const List<String> hourListConfig = ['1', '2', '3','4', '5', '6', '7','8', '9', '10', '11','12'];
    

    正如 Flutter 团队所说,每个小部件都有一个元素,当您尝试在下拉列表中呈现相同的对象类型时,它会跟踪其状态,它不会呈现新列表。

    如果您希望小部件树确保以 2 种不同的方式呈现下拉小部件,那么您将必须使用 KEY

    在这种情况下,Object 键可用于确保在后台颤振中为两种情况创建 2 个不同的下拉列表,并且不会将下拉列表呈现为 1 个小部件。

    return CustomDropDown(
        key: ObjectKey(chosenValue),
        isExpanded: false,
        dropDownList: dropDownList,
        defaultVal:
            isMinutesWidget ? defaultMinuteSelected : defaulHourSelected,
        dropDownType: DropDownType.DROPDOWN_WITH_ARROW,
        selectedItem: (String selectedVal, DropDownsType dropDownId) {
          if (isMinutesWidget) {
            defaultMinuteSelected = selectedVal;
          } else {
            defaulHourSelected = selectedVal;
          }
        },
        customDropDownId: DropDownsType.CustomId,
      );
    
    
    
    
      if (widget.dropDownType == DropDownType.DROPDOWN_WITH_ARROW) {
          return Material(
            elevation: 10,
            color: foreground_color,
            borderRadius: BorderRadius.circular(10.r),
            child: Padding(
              padding: EdgeInsets.symmetric(horizontal: 5.w),
              child: DropdownButton<String>(
                key:widget.key
                value: chosenValue,
                isExpanded: widget.isExpanded,
                dropdownColor: foreground_color,
                icon: const Icon(Icons.keyboard_arrow_down_rounded),
                borderRadius: BorderRadius.circular(10.r),
                underline: const SizedBox(),
                style: const TextStyle(color: Colors.white),
                iconEnabledColor: Colors.white,
                items: widget.dropDownList
                    .map<DropdownMenuItem<String>>((String value) {
                  return DropdownMenuItem<String>(
                    value: value,
                    child: Text(
                      value,
                      style: const TextStyle(color: Colors.white),
                    ),
                  );
                }).toList(),
                onChanged: (String? value) {
                  if (value != null) {
                    setState(() {
                      chosenValue = value;
                      widget.selectedItem(chosenValue, widget.customDropDownId);
                    });
                  }
                },
              ),
            ),
          );
    

    Flutter 团队按键视频

    https://www.youtube.com/watch?v=kn0EOS-ZiIc

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-08-30
      • 2015-10-28
      • 1970-01-01
      • 2011-11-24
      • 1970-01-01
      • 1970-01-01
      • 2011-12-16
      相关资源
      最近更新 更多