Как сделать этот виджет раскрывающейся кнопки многоразовым?

#flutter #dart

Вопрос:

У меня есть виджет кнопки выпадающего списка ниже, с futurebuilder, который считывает список из электронной таблицы Google. Виджет работает хорошо, как и предполагалось.

Я хочу повторно использовать этот виджет в приложении и просто передать другое будущее

Например, я хочу вызвать один и тот же виджет, но передать разные списки mydropdownbutton ( futureList1 ), mydropdownbutton ( futureList2 ), mydropdownbutton ( futureList3 ),

 //========================================================
// WIDGET: FUTURE DROPDOWN MENU   FUTURE LIST
//--------------------------------------------------------
  class dropDownButtonWidget extends StatefulWidget {
    const dropDownButtonWidget({ Key? key,}) : super(key: key);
    @override
    State<dropDownButtonWidget> createState() => _dropDownButtonWidgetState();
  }
// --------------------------------------------------------
  class _dropDownButtonWidgetState extends State<dropDownButtonWidget> {
    @override
    Widget build(BuildContext context) {
      return Center(
          child: FutureBuilder(future: futureList(),
            builder: (BuildContext context, AsyncSnapshot<List> snapshot) {
              if(snapshot.hasData){ List? futureDataList = snapshot.data;
                  futureDataList ??= ['Loading']; //if snapshot is null
                  return buildDropdownButton(dropdownList: futureDataList );
              }else if (snapshot.hasError) {
                  return Center(child: Text(snapshot.error.toString()));
              }else {
                  return Center(child: CircularProgressIndicator());
              }
          }
        )
      );
    }
    //----------------------------------
    // DROPDOWNBUTTON EXTRACTED METHOD
      DropdownButton<Object> buildDropdownButton({required List dropdownList}) {
        String defaultValue = dropdownList.first; //DEFAULT SELECTED ITEM
          return DropdownButton(
                  value: defaultValue,
                  onChanged: (value) => setState(() => defaultValue = value.toString()),
                  items: dropdownList.map((items) {
                      return DropdownMenuItem(value: items, child: Text(items));
                    }).toList(),
                  );
       }
    //----------------------------------
  }
//=============================================

//=============================================
//FUTURE LIST FOR THE DROPDOWN MENU
//=============================================
  Future<List> futureList() async {
    var items = await ScheduleInfo.mx_schedule_WEEKDAYS_as_List(debugONOFF: 1);
    return items;}
//=============================================
 

Как я могу сделать этот виджет модульным и многоразовым?

Комментарии:

1. Что вы подразумеваете под многоразовым использованием?

2. @Anye это означает, что один и тот же код можно использовать повторно,точно так же, как повторно используемую функцию sumFunct(a, b){return a b}. Вы можете вызывать эту функцию столько раз, сколько потребуется. Виджеты также можно использовать повторно.

Ответ №1:

вы можете отправить будущее в конструктор этого виджета. сначала вы объявляете переменную и устанавливаете ее в конструктор. затем вы можете ссылаться на эту переменную в состоянии этого класса по widget.variable ключевому слову. что-то вроде этого

 class dropDownButtonWidget extends StatefulWidget {
    final variable;
    dropDownButtonWidget(this.variable);
    const dropDownButtonWidget({ Key? key,}) : super(key: key);
    @override
    State<dropDownButtonWidget> createState() => _dropDownButtonWidgetState();
  }

class _dropDownButtonWidgetState extends State<dropDownButtonWidget> {
widget.variable //whatever you want to do with it
}
 

Комментарии:

1. Спасибо за пример, но он выдает ошибку: конструктор уже существует. Даже несмотря на то, что я исправил это, объединив два конструктора, я все еще не могу создать модульный виджет. Судя по моим показаниям, совместное использование переменных кажется более сложным. Вероятно, мне нужно будет использовать наследование виджетов. В настоящее время изучается резолюция.

Ответ №2:

Сообщество… после нескольких часов чтения и тестирования я нашел решение своего собственного вопроса. Я публикую решение для всех, кто в нем нуждается.

Возможно, мой код можно улучшить, я приветствую предложения.

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

Ниже мой собственный ответ: тот же виджет преобразован в многоразовый модульный виджет.

( Это работает только с будущими списками (асинхронно) )

Простой ВИДЖЕТ ЭКРАНА (с вложенными виджетами раскрывающихся кнопок):

 class Screen01 extends StatefulWidget {
  const Screen01({
    Key? key,
  }) : super(key: key);

  @override
  State<Screen01> createState() => _Screen01State();
}

class _Screen01State extends State<Screen01> {
  @override
  Widget build(BuildContext context) {
    return Center(child:
        Flex(
          direction: Axis.horizontal, 
          crossAxisAlignment: CrossAxisAlignment.center, 
          mainAxisAlignment: MainAxisAlignment.center,

          children:
            [ // each time you call the widget, you can provide a different future list          
              dropDownButtonWidgetModular(futureList: dropdownFutureList()), 

              SizedBox(width: 50,),

              dropDownButtonWidgetModular(futureList: anotherFutureList())
            ]
      ),
    );
  }
}
 

ВИДЖЕТ РАСКРЫВАЮЩЕЙСЯ КНОПКИ:

 //========================================================
// WIDGET: FUTURE DROPDOWN MENU   FUTURE LIST
//--------------------------------------------------------
class dropDownButtonWidgetModular extends StatefulWidget {

  final Future<List> futureList; // ===> ADDED FUTURE LIST
  const dropDownButtonWidgetModular({ Key? key, required this.futureList}) : super(key: key); // ===> ADDED REQUIRED FUTURE LIST

  @override
  State<dropDownButtonWidgetModular> createState() => _dropDownButtonWidgetModularState(chosenFutureList: futureList);
}
// --------------------------------------------------------
class _dropDownButtonWidgetModularState extends State<dropDownButtonWidgetModular> {

  Future<List> chosenFutureList; // ===> ADDED FUTURE LIST
  String? defaultValue;

  _dropDownButtonWidgetModularState({required this.chosenFutureList}); // ===> ADDED REQUIRED FUTURE LIST

  @override
  Widget build(BuildContext context) {
    return Center(child:
    FutureBuilder(future: chosenFutureList, // ===> ADDED FUTURE LIST
        builder: (BuildContext context, AsyncSnapshot<List> snapshot) {
          if(snapshot.hasData){ List? futureDataList = snapshot.data;
            futureDataList ??= ['Loading']; //if snapshot is null
            return buildDropdownButton(dropdownList: futureDataList );
          }else if (snapshot.hasError) {
            return Center(child: Text(snapshot.error.toString()));
          }else {
            return Center(child: CircularProgressIndicator());
          }
        }
    )
    );
  }
  //----------------------------------
  // DROPDOWNBUTTON EXTRACTED METHOD
  DropdownButton<Object> buildDropdownButton({required List dropdownList}) {

    defaultValue ??= dropdownList.first; //DEFAULT SELECTED ITEM

    return DropdownButton(
      value: defaultValue,
      onChanged: (value) => setState(() => defaultValue = value.toString()),
      items: dropdownList.map((items) {
        return DropdownMenuItem(value: items, child: Text(items));
      }).toList(),
    );
  }
//----------------------------------
}
//=============================================
 

Я прокомментировал некоторые изменения, внесенные в мой первоначальный вопрос