1. 提出问题
上面是我们常见的一个效果图,按照常理我们的实现代码如下:
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<String> cuntries = <String>[
'北京',
'上海',
'成都',
'西安',
'太原',
'云南',
];
int _selectedCountryIndex = 0;
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
_showDialog();
});
}
_showDialog() async {
await showDialog(
context: context,
builder: (BuildContext context) {
return new CupertinoAlertDialog(
title: new Text('请选择'),
actions: <Widget>[
new CupertinoDialogAction(
isDestructiveAction: true,
onPressed: () {
Navigator.of(context).pop('取消');
},
child: new Text('取消')),
new CupertinoDialogAction(
isDestructiveAction: true,
onPressed: () {
Navigator.of(context).pop('确定');
},
child: new Text('确定')),
],
content: new SingleChildScrollView(
child: new Material(
child: _buildList(),
),
),
);
});
}
_buildList() {
if (cuntries.length == 0) return Container();
return new Column(
children:
new List<RadioListTile<int>>.generate(cuntries.length, (int index) {
return new RadioListTile(
value: index,
groupValue: _selectedCountryIndex,
title: new Text(cuntries[index]),
onChanged: (int value) {
setState(() {
_selectedCountryIndex = value;
});
});
}),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Container(),
// This trailing comma makes auto-formatting nicer for build methods.
);
}
}
运行之后点击条目,发现并不能刷新dialog的界面。
2. 解决办法
我们可以将dialog的内容部分抽取出来用一个StatefulWidget来实现,如下所示:
import 'package:flutter/material.dart';
class MyDialogContent extends StatefulWidget {
final List<String> cuntries;
MyDialogContent({Key key, this.cuntries}) : super(key: key);
@override
_MyDialogContentState createState() => _MyDialogContentState();
}
class _MyDialogContentState extends State<MyDialogContent> {
int _selectedIndex = 0;
_getContent() {
if (widget.cuntries.length == 0) {
return new Container();
}
return new Column(
children: new List<RadioListTile<int>>.generate(widget.cuntries.length,
(int index) {
return new RadioListTile(
value: index,
groupValue: _selectedIndex,
title: new Text(widget.cuntries[index]),
onChanged: (int value) {
setState(() {
_selectedIndex = value;
});
});
}),
);
}
@override
Widget build(BuildContext context) {
return _getContent();
}
}
将问题代码中的_buildList方法替换成下面代码
new MyDialogContent(
cuntries: cuntries,
)
3.解决后的最终代码
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<String> cuntries = <String>[
'北京',
'上海',
'成都',
'西安',
'太原',
'云南',
];
int _selectedCountryIndex = 0;
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
_showDialog();
});
}
_showDialog() async {
await showDialog(
context: context,
builder: (BuildContext context) {
return new CupertinoAlertDialog(
title: new Text('请选择'),
actions: <Widget>[
new CupertinoDialogAction(
isDestructiveAction: true,
onPressed: () {
Navigator.of(context).pop('取消');
},
child: new Text('取消')),
new CupertinoDialogAction(
isDestructiveAction: true,
onPressed: () {
Navigator.of(context).pop('确定');
},
child: new Text('确定')),
],
content: new SingleChildScrollView(
child: new Material(
child: new MyDialogContent(
cuntries: cuntries,
),
),
),
);
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Container(),
);
}
}