#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(),
);
}
//----------------------------------
}
//=============================================
Я прокомментировал некоторые изменения, внесенные в мой первоначальный вопрос