#flutter #dart #flutter-widget
#флаттер #dart #flutter-виджет
Вопрос:
Я новичок в flutter.
У меня есть страница (виджет с отслеживанием состояния) в приложении с множеством виджетов в столбце. Чтобы улучшить читаемость кода, я взял несколько виджетов и разделил их на отдельные классы. Например, я превратил свой виджет dropdownmenu в его единственный класс, например, так:
class DropDownMenuWidget extends StatefulWidget {
DropDownMenuWidget({Key? key}) : super(key: key);
@override
_DropDownMenuWidgetState createState() => _DropDownMenuWidgetState();
}
/// This is the private State class that goes with MyStatefulWidget.
class _DropDownMenuWidgetState extends State<DropDownMenuWidget> {
String dropdownValue = 'One';
@override
Widget build(BuildContext context) {
return DropdownButton<String>(
value: dropdownValue,
icon: Icon(Icons.arrow_downward),
iconSize: 24,
elevation: 16,
style: TextStyle(
color: Colors.black,
fontSize: 20,
),
underline: Container(
height: 2,
color: Colors.blue,
),
onChanged: (String? newValue) {
setState(() {
dropdownValue = newValue!;
});
},
items: MASLULIM
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
);
}
}
Теперь в родительском классе я отображаю виджет следующим образом:
DropDownMenuWidget(),
Однако проблема в том, что когда пользователь нажимает на элемент, я могу получить это значение только из класса DropDownMenu , и там вызывается метод setState() . Однако мне нужно прочитать это значение в родительском классе. Как я могу получить его там?
Спасибо
Ответ №1:
Вместо того, чтобы создавать свою dropdownValue
переменную в своем виджете, вы можете получить ее из родительского виджета следующим образом с помощью ValueNotifier
class DropDownMenuWidget extends StatefulWidget {
ValueNotifier dropdownValueNotifier;
DropDownMenuWidget(this.dropdownValueNotifier, {Key key}) : super(key: key);
@override
_DropDownMenuWidgetState createState() => _DropDownMenuWidgetState();
}
class _DropDownMenuWidgetState extends State<DropDownMenuWidget> {
@override
Widget build(BuildContext context) {
return ValueListenableBuilder(
valueListenable: widget.dropdownValueNotifier,
builder: (context, dropdownValue, _) {
return DropdownButton<String>(
value: dropdownValue,
// ...
onChanged: (String newValue) {
// simply change the value. You dont need setState anymore
widget.dropdownValueNotifier.value = newValue;
},
// ...
);
},
);
}
}
В родительском виджете создайте переменную и передайте ее следующим образом
ValueNotifier dropdownValueNotifier = ValueNotifier('One');
// ...
DropDownMenuWidget(dropdownValueNotifier),
Комментарии:
1. Вот как я получаю переменную для виджета, но как мне вернуть ее родительскому, когда пользователь выбирает ее? Спасибо
2. Сначала создайте переменную в родительском виджете, затем передайте ее дочерним по параметру. Как вы можете видеть выше
3. Я понимаю, что вы говорите, но тогда пользователь выберет другое значение в виджете, и это значение должно быть прочитано родителем
4. Лучшим подходом для этого является использование
ValueNotifier
5. Проверьте новое решение
Ответ №2:
В этом случае вы можете использовать typedef
Сначала в отдельном выпадающем меню вы можете создать следующий значок вне класса:
typedef OnItemSelectedDropDown = Function (String value);
Теперь вы можете применить это следующим образом :
class DropDownMenuWidget extends StatefulWidget {
final OnItemSelectedDropDown onItemSelected ;
DropDownMenuWidget({Key? key}) : super(key: key);
@override
_DropDownMenuWidgetState createState() => _DropDownMenuWidgetState();
}
/// This is the private State class that goes with MyStatefulWidget.
class _DropDownMenuWidgetState extends State<DropDownMenuWidget> {
String dropdownValue = 'One';
@override
Widget build(BuildContext context) {
return DropdownButton<String>(
value: dropdownValue,
icon: Icon(Icons.arrow_downward),
iconSize: 24,
elevation: 16,
style: TextStyle(
color: Colors.black,
fontSize: 20,
),
underline: Container(
height: 2,
color: Colors.blue,
),
onChanged: (String value) {
//This line return Value
widget.onItemSelected.call(value);
},
items: MASLULIM
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
);
}
}
При вызове класса DropDownMenuWidget
он вызывается следующим образом на другом экране:
String dropdownValue ;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('DropDown Page'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'New Value DropDown : $dropdownValue',
),
DropDownMenuWidget(
onItemSelected :(newValue){
setState(() {
dropdownValue = newValue ;
});
}
),
],
),
),
);
}