背景
在一个界面中,弹出一个Dialog,然后在Dialog有一些交互,通过点击一些按钮来改变界面中的一些值,而Dialog又根据这些值显示不同的内容。
如上图,创建专集的界面上,弹出了一个选择专集类型的Dialog,然后点击Dialog中不同的条目,改变界面上的selected字段的值,而Dialog又是根据selected来确定在哪一个条目上线上“对号”
有问题的代码:
class EditAlbumPage extends StatefulWidget {
...........
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return EditAlbumState();
}
}
class EditAlbumState extends State<EditAlbumPage> {
............
@override
Widget build(BuildContext context) {
...........
return GestureDetector(
onTap: () {
if (widget.create) {
showModalBottomSheet(
backgroundColor: Colors.transparent,
context: context,
builder: (context) {
return Container(
/// dialog 的具体界面内容
);
});
}
},
这样写完之后,点击dialog中的其他item,然后通过setState方式去修改selected的值,但是dialog的界面却不会刷新。
因为dialog中的内容实际上实在一个新的page中显示的,与父界面并不是一个界面。所以通过setState方法刷新父界面的值,并不会让Dialog的界面也刷新。
解决方案
把Dialog的内容单独写到一个StatefulWidget中,通过一个属性变更来更新自己的UI。
那么问题来了,新的Dialog怎么把选中的属性数据传递给父界面呢?
方式有很多种,其中最简单的一种方式边上回调方法。
/// 父界面中显示Dialog
return GestureDetector(
onTap: () {
showModalBottomSheet(
backgroundColor: Colors.transparent,
context: context,
builder: (context) {
return CreateAlbumDialog(currentModel, (currentSelect) {
setState(() {
currentModel = dataTypeList[currentSelect];
});
});
});
},
........
class CreateAlbumDialog extends StatefulWidget {
final Function selectListener;
CreateAlbumDialog(this.model, this.selectListener);
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return _State();
}
}
class _State extends State<CreateAlbumDialog> {
int currentSelected;
.........
.........
@override
Widget build(BuildContext context) {
// TODO: implement build
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.only(topLeft: Radius.circular(20), topRight: Radius.circular(20)),
color: DColor.mainViewBgColor,
),
padding: EdgeInsets.only(left: 16, right: 16, top: 16),
child: Column(
children: <Widget>[
Text(
"选择专集类型",
style: TextStyle(fontSize: 16, color: Color.fromRGBO(47, 54, 65, 1), fontWeight: FontWeight.bold),
),
SizedBox(
height: 8,
),
Text(
"每类最多支持创建5个",
style: DTextStyle.commonText1440,
),
SizedBox(
height: 8,
),
Expanded(
child: ListView.separated(
// physics: NeverScrollableScrollPhysics(),
scrollDirection: Axis.vertical,
itemCount: dataTypeList.length,
itemBuilder: (context, index) {
return itemWidget(index, index == currentSelected);
},
separatorBuilder: (context, index) {
return Divider(
height: 0.5,
);
},
),
)
],
),
);
}
Widget itemWidget(int index, bool selected) {
......
return GestureDetector(
onTap: () {
setState(() {
currentSelected = index;
/// 通过一个回调方法,把值传递给父界面中
/// 通过一个回调方法,把值传递给父界面中
/// 通过一个回调方法,把值传递给父界面中
widget.selectListener(currentSelected);
});
},
child: Container(
height: 53,
color: DColor.mainViewBgColor,
child: Row(
children: <Widget>[
Text(
typeModel.name,
style: DTextStyle.commonText16100,
),
SizedBox(
width: 8,
),
Expanded(
child: Text(
numStr,
style: DTextStyle.commonText1240,
),
),
selected
? Image.asset(
"assets/images/icon/selected_square.png",
width: 22,
height: 22,
)
: SizedBox()
],
),
),
);
}
}