在Flutter應用開發中,常常會遇到自定義彈框的開發需求,以下圖所示。
對於這種樣式,咱們能夠選擇自定義Dialog,具體的樣式能夠根據本身的須要進行修改。 例如,下面是個人實現,因爲文本是一個列表,因此我須要新建一個實體類,以下所示。json
class IntroduceModel { int code; List<Data> data; IntroduceModel({this.code, this.data}); IntroduceModel.fromJson(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,源碼以下:async
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風格的樣式(即不帶有下換線),解決的方法有三個:ide
解決方案主要有三種:
1,採用根節點爲腳手架Scaffold組件:ui
Scaffold(body: content,);
2, 採用根節點爲Material 組件。this
Material(child: content);
3, 逐個修改Text 組件的style 下的decoration爲TextDecoration.none。spa
child: Text( "專欄的文章", overflow: TextOverflow.ellipsis, style: TextStyle( decoration: TextDecoration.none, color: Color(0xFF888888), fontSize: 14, fontWeight: FontWeight.bold, fontFamily: defaultFontFamily, ), )
對於間距,只須要使用Offstage組件便可。最後,在須要使用的地方調用一下這個組件便可,以下所示。code
showIntroduceDialog(BuildContext context) async { var localData=await rootBundle.loadString('assets/flow_advertis_funnel.json'); IntroduceDialog.showUpdateDialog(context, '數聽說明', localData, false); }