flutter 自定義彈框
阿新 • • 發佈:2020-09-21
在Flutter應用開發中,經常會遇到自定義彈框的開發需求,如下圖所示。
對於這種樣式,我們可以選擇自定義Dialog,具體的樣式可以根據自己的需要進行修改。 例如,下面是我的實現,由於文字是一個列表,所以我需要新建一個實體類,如下所示。
class IntroduceModel {
int code;
List<Data> data;
IntroduceModel({this.code, this.data});
IntroduceModel.from
json(Map<String, dynamic> json) {
code = json['code'];
if (json['data'] != null) {
data = new List<Data>();
json['data'].forEach((v) {
data.add(new Data.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['code'] = this.code;
if (this.data != null) {
data['data'] = this.data.map((v) => v.toJson()).toList();
}
return data;
}
}
class Data {
String itemTitle;
String itemContent;
Data({this.itemTitle, this.itemContent});
Data.fromJson(Map<String, dynamic> json) {
itemTitle = json['itemTitle'];
itemContent = json['itemContent'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['itemTitle'] = this.itemTitle;
data['itemContent'] = this.itemContent;
return data;
}
}
然後,我們自定義一個Dialog,原始碼如下:
class IntroduceDialog extends Dialog {
String des='注:以上的單⽇⽬標額從實際年⽬標額、⽉⽬標額取平均值計算⽽來。';
String title;
String content;
bool isForce;
IntroduceModel model;
IntroduceDialog({this.title, this.content,this.isForce}){
if(content!=null){
model=IntroduceModel.fromJson(json.decode(content));
}
}
@override
build(BuildContext context) {
return Material(
type: MaterialType.transparency,
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
_buildContent(context),
_buildClose(context)
],
),
),
);
}
_buildContent(BuildContext context) {
double sWidth= MediaQuery.of(context).size.width;
return Container(
color: Colors.white,
width: sWidth*0.85,
height: 420,
padding: EdgeInsets.only(left: 15,right: 15,top: 10,bottom: 10),
child: SingleChildScrollView(
child: Column(
children: [
Text(title, style: TextStyle(fontSize: 20,color:Colors.black,fontWeight: FontWeight.bold)),
SizedBox(height: 5),
_buildListView(),
Text(des, style: TextStyle(fontSize: 14)),
],
),
),
);
}
_buildListView() {
return Container(
padding: EdgeInsets.only(top: 5,bottom:5,right: 0,),
child: ListView.separated(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: model.data.length,
separatorBuilder: (BuildContext context, int index) => Container(
child: divider(),
),
itemBuilder: (context, index) {
return _buildItem(context,model.data, index);
},
),
);
}
_buildItem(BuildContext context, list, int index) {
Data item=list[index];
return Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(item.itemTitle, style: TextStyle(fontSize: 14)),
Text(item.itemContent, style: TextStyle(fontSize: 14)),
],
);
}
_buildClose(BuildContext context) {
return GestureDetector(
child: Offstage(
offstage: isForce,
child: Container(
margin: EdgeInsets.only(top: 30),
child: LoadAssetImage('close_icon', width: 45,height: 45,fit: BoxFit.fill,)
),
),
onTap: (){
Navigator.of(context).pop();
},
);
}
static showUpdateDialog(BuildContext context, String title,String content, bool isForce) {
return showDialog(
barrierDismissible: false,
context: context,
builder: (BuildContext context) {
return WillPopScope(
child: IntroduceDialog(title: title,content: content, isForce: isForce),onWillPop: _onWillPop);
});
}
static Future<bool> _onWillPop() async{
return false;
}
}
需要說的是,自定義的Dialog的根元件需要使用Material,不然的話,Dialog介面的文字下面會出現黃色的下劃線,導致這種情況發生的原因是因為,Text widget 隸屬於Material 風格下的元件,如果根節點不是Material 相關元件,則會使用預設帶黃色下劃線的格式。如果根節點是Material 容器元件,則會採用其Material風格的樣式(即不帶有下換線),解決的方法有三個:
廣州vi設計http://www.maiqicn.com 辦公資源網站大全https://www.wode007.com
解決方案主要有三種:
1,採用根節點為腳手架Scaffold元件:
Scaffold(body: content,);
2, 採用根節點為Material 元件。
Material(child: content);
3, 逐個修改Text 元件的style 下的decoration為TextDecoration.none。
child: Text(
"專欄的文章",
overflow: TextOverflow.ellipsis,
style: TextStyle(
decoration: TextDecoration.none,
color: Color(0xFF888888),
fontSize: 14,
fontWeight: FontWeight.bold,
fontFamily: defaultFontFamily,
),
)
對於間距,只需要使用Offstage元件即可。最後,在需要使用的地方呼叫一下這個元件即可,如下所示。
showIntroduceDialog(BuildContext context) async {
var localData=await rootBundle.loadString('assets/flow_advertis_funnel.json');
IntroduceDialog.showUpdateDialog(context, '資料說明', localData, false);
}