Пользовательский виджет не отображается

#flutter #dart #widget #dropdown

Вопрос:

Я сделал пользовательский выбор выпадающего списка, проблема в том, что при его переключении виджет не отображается

В пользовательском интерфейсе есть 2 раскрывающихся списка. В разных случаях раскрывающийся список «Ребенок» может быть виден или не виден.

Проблема возникает только в том случае, если у меня есть как родительские, так и дочерние раскрывающиеся списки, и в следующем случае оба раскрывающихся списка будут видны.

Ниже приведены примеры того, как визуализируется мой динамический пользовательский интерфейс

случай 1 ) Выпадающий список 1 и Выпадающий список 2 в пользовательском интерфейсе (Выпадающий список 2-родительский виджет)

когда пользователь нажимает на выпадающие 2 элемента, отображается основной пользовательский интерфейс.

(Выпадающие 2 пункта Минуты, Часы, День, Неделя) Выпадающий 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 Минута, а затем выбирает любой другой элемент, кроме часов, дочерний раскрывающийся список удаляется из пользовательского интерфейса. Но когда пользователь выбирает часы через минуту, элементы в дочернем виджете отображаются, но значение по умолчанию этого значения не выбирает новое значение, оно сохраняет старые данные, которые были выбраны за считанные минуты, так как пользовательский интерфейс не был уничтожен.

Ответ №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 различными способами, вам придется использовать клавишу

В этом случае ключ объекта можно использовать, чтобы убедиться, что в фоновом режиме flutter создает 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