сохранить состояние из внешнего виджета
У меня есть внешний каркас с панелью приложения с кнопкой действия, при нажатии которой я хочу сохранить состояние внутреннего виджета с отслеживанием состояния в перманентном хранилище - как лучше всего иметь возможность вызывать метод внутреннего виджета из внешней панели приложения а также иметь возможность делать Scaffold.of(context) в вызываемом методе?
class AISSettings extends StatelessWidget {
static const String route = 'settings/ais';
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('AIS settings'),
actions: <Widget>[
IconButton(icon: Icon(Icons.check), onPressed: () => {/* call _SettingsState.saveStuff() */} ),
],
),
bottomNavigationBar: Navbar(),
body: AISSettingsForm(),
);
}
}
class AISSettingsForm extends StatefulWidget {
@override
_SettingsState createState() => _SettingsState();
}
class _SettingsState extends State<AISSettingsForm> {
final _formKey = GlobalKey<_SettingsState>();
Map<String, dynamic> _options;
saveStuff() {
// Scaffold.of(context).showSnackBar(....)
}
}
2 ответа
Вы должны сделать внешний класс с сохранением состояния, а внутренний класс без состояния или с сохранением состояния, чтобы метод setState() внешнего класса отражался во внутреннем классе. ниже я привожу ваш пример с некоторыми изменениями.
class AISSettings extends StatefulWidget {
static const String route = 'settings/ais';
final _formKey = GlobalKey<_SettingsState>();
Map<String, dynamic> _options;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('AIS settings'),
actions: <Widget>[
IconButton(icon: Icon(Icons.check), onPressed: () => {/* call _SettingsState.saveStuff() */} ),
],
),
//bottomNavigationBar: Navbar(),
body: AISSettingsForm(),
);
}
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return null;
}
}
class AISSettingsForm extends StatefulWidget {
@override
_SettingsState createState() => _SettingsState();
}
class _SettingsState extends State<AISSettingsForm> {
saveStuff() {
// Scaffold.of(context).showSnackBar(....)
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return null;
}
}
Это то, что у меня получилось, что позволяет мне сохранять настройки с помощью кнопки панели приложений и отображать закусочную. В другом компоненте с представлением с вкладками я поднял состояние и передал виджет State в дочерние виджеты TabBarView, чтобы они могли обновить состояние.
class AISSettings extends StatefulWidget {
static const String route = 'settings/ais';
@override
_SettingsState createState() => _SettingsState();
}
class _SettingsState extends State<AISSettings> {
final _formKey = GlobalKey<_SettingsState>();
Map<String, dynamic> _options;
saveStuff(context) {
// do stuff to save the settings to perm storage....
Scaffold.of(context).showSnackBar(....)
}
setValue(key, value) {
setState(() => _options[key] = value);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('AIS settings'),
actions: <Widget>[
Builder(
builder: (context) => IconButton(
icon: Icon(Icons.check),
onPressed: () => {saveStuff(context)}),
)
],
),
bottomNavigationBar: Navbar(),
body: ListView(
children: [
StatelessWidget1(this, _options),
StatelessWidget2(this, _options),
StatelessWidget3(this, _options),
])
);
}
}
class StatelessWidget1 extends StatelessWidget {
final Map<String, dynamic> settings;
final _SettingsState parent;
StatelessWidget1(this.parent, this.settings);
@override
Widget build(BuildContext context) {
return Slider(
key: Key('variation'),
min: -20.0,
max: 20.0,
label: '${settings['variation']}\u00B0',
divisions: 40,
value: 0.0 + settings['variation']
onChanged: (val) => parent.setValue('variation', val),
);
}
}