flutter 自定义弹框

更新日期: 2020-07-31阅读: 1.8k标签: Flutter

在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);
  }

链接: https://fly63.com/article/detial/9611

移动跨平台框架Flutter介绍和学习线路

Flutter是一款移动应用程序SDK,一份代码可以同时生成iOS和Android两个高性能、高保真的应用程序。Flutter目标是使开发人员能够交付在不同平台上都感觉自然流畅的高性能应用程序。我们兼容滚动行为、排版、图标等方面的差异。

初识flutter

关注flutter已经好久,因为没有发正式版,所以一直也不想过早的躺浑水,但是最近无意中看到几篇文章,再加上美团和咸鱼等app也一直在做灰度测试,所以上周开始看了一下官方文档,地址:https://flutter.io/docs/get-started/install,然后在此做一下总结。

深入理解Flutter多线程

Flutter默认是单线程任务处理的,如果不开启新的线程,任务默认在主线程中处理。和iOS应用很像,在Dart的线程中也存在事件循环和消息队列的概念,但在Dart中线程叫做isolate。

Flutter1.5 开始,将成为全平台 UI 框架!

Flutter 1.5 的发布,同期也宣布发布 Flutter for Web 的 Preview 版本,正式开启了 Flutter 的全平台 UI 框架之路。早在年初发布的 Flutter 2019 Roadmap 中,就有提到,会在今年支持移动设备之外的平台,对 Web 的支持,算是完成了一个新的里程碑吧。

Flutter支持Web开发了!

Flutter作为一个可移植的UI框架,已经支持现代Web应用开发了!我们很开心已经发布了SDK预览版,这样你可以在Web浏览器里直接运行你的Flutter UI代码。

Flutter 混合开发 (交互通信)

Flutter 与原生之间的通信依赖灵活的消息传递方式:1,Flutter 部分通过平台通道将消息发送到其应用程序的所在的宿主环境(原生应用)。2,宿主环境通过监听平台通道,接收消息。

Flutter 局部路由实现

Flutter是借鉴React的开发思想实现的,在子组件的插槽上,React有this.props.children,Vue有<slot></slot>。当然Flutter也有类似的Widget,那就是Navigator,不过是以router的形式实现(像<router-view></router-view>)。

Flutter Kotlin 到底该如何选择?

这两个技术在当下如何选择,我之前在公众号上的回复是:如果你已经处于一个比较满意的公司,并考虑长期发展,公司并未使用这两个技术,你可以专心钻研公司当下使用的,或者未来将要使用的,这些才能助你在公司步步高升。

Flutter 与 iOS 原生 WebView 对比

本文对比的是 UIWebView、WKWebView、flutter_webview_plugin(在 iOS 中使用的是 WKWebView)的加载速度,内存使用情况。测试网页打开的速度,只需要获取 WebView 在开始加载网页和网页加载完成时的时间戳

Flutter For Web

用来构建漂亮、定制化应用的跨平台的 UI 框架 Flutter 现在已经支持 Web 开发了。我们很高兴推出了一个预览版的 SDK 可以让开发者直接使用 Flutter UI 和业务逻辑代码构建 web 应用

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!