在Flutter利用开发中,常常会遇到自定义弹框的开发需要,如下图所示。

对于这种款式,咱们能够抉择自定义Dialog,具体的款式能够依据本人的须要进行批改。 例如,上面是我的实现,因为文本是一个列表,所以我须要新建一个实体类,如下所示。

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,源码如下:

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格调的款式(即不带有下换线),解决的办法有三个:

解决方案次要有三种:
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);  }