动手造轮子——用Builder模式撸一个通用版本的Dialog 前言
在Android开发中我们常常需要使用Dialog来处理一些弹窗操作。虽然Android系统本身为我们封装了一个自带的弹窗Dialog,但是由于Android操作系统的不同,导致了每个手机弹窗页面的不同,以至于我们很难用系统的去统一样式。并且UI会觉得系统的弹窗过于丑陋,希望自己来做一个于是我们便需要自己来处理一个Dialog弹窗。今天叫大家利用Builder构造者模式自己来封装一个弹窗Dialog。
需求分析
首先确定一下,弹窗我们需要哪些功能?
- 需要可以自己自定义样式。因为每个弹窗会根据逻辑和需求的不同拥有不同的样式。例如有些弹窗有title标题,有些只有message提示;有些有确定和取消按钮,有些又只有一个确定按钮。我们必须用一套代码来加载不同的样式才行。
- 设置title或者message的内容。这里可以根据传入的不同id设置不同文字内容。
- 设置按钮的点击事件
- 设置是否需要点击弹窗外部使得弹窗消失。
开始操作
分析完了需求之后我们便可以根据需求来撸代码了。
首先我们写一个CommonDialog类让他继承Dialog。 此时我们必须复写onCreat(),在onCreat()我么进行一些设置操作。这里我们设置setContentView()加载布局样式,设置setCancelable()是否点击弹窗以外使得弹窗消失。
public class CommonDialog extends Dialog { private Context context; private View view; private boolean cancelTouchout; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(view); setCancelable(cancelTouchout); } }
其实这时候我们就开始要编写Builder构造者模式的代码了。
构造者模式,顾名思义,就是根据我们的需要往代码上添加需求。例如,我们需要设置title标题的内容,此时我们就添加上这个功能,如果需要设置message内容的功能我们也设置上这个功能。如果不需要则不添加这段代码。
先根据不同样式加载不同的布局。此时我们利用LayoutInflater来处理。布局样式由参数传递进来。
public Builder view(int resView) { view = LayoutInflater.from(context).inflate(resView, null); return this; }
其次,再根据是否可以点击弹窗外部使得弹窗消失。
public Builder cancelTouchout(boolean val) { cancelTouchout = val; return this; }
传入的val若为true代表可以消失,如果传入的为false则代表不能消失。
紧接着我们再来看看如果根据title和message来设置不同的内容。 这里我们的参数设置为两个,一个是需要设置内容的id,一个是设置内容的文字title/message。我们先通过findViewById去查找到这个View中的控件,之后再根据文字内容将文字设置到控件上去。
//设置标题title public Builder setTitle(int viewRes,String title){ TextView txtTitle = (TextView) view.findViewById(viewRes); txtTitle.setText(title); return this; } //设置内容message public Builder setMessage(int viewRes,String message){ TextView txtMessage = (TextView)view.findViewById(viewRes); txtMessage.setText(message); return this; }
然后我们就该去设置点击事件了。 点击事件我们可以借鉴设置title和message的情况来处理,通过传入一个点击控件的id来查找id,之后通过View.OnClickListener来回调这个点击事件处理点击逻辑即可。
public Builder addViewOnclick(int viewRes,View.OnClickListener listener){ view.findViewById(viewRes).setOnClickListener(listener); return this; }
最后我们只需要把最后写一个build返回一个CommonDialog即可。但是如果此时我们调用使用这个CommonDialog时你会发现我们不管如何设置加载的View,发现大小其实都是不变的。这是怎么回事?其实这是因为我们的背景色一起被设置进入了View布局中。如果此时我们把我们加载的View背景设置为黑色(#000000),就会神奇的发现,在View旁边还有一些白色的存在。正是因为这些白色,导致了我们无论如何设置弹窗宽度都显示的是原来的大小。如果你要设置为圆角,那更是不太可能。
那该如何处理这种情况?其实很简单,我们仅仅需要设置一下将弹窗风格的style设置一个透明的背景即可处理好这种情况。
我们在value-style中设置一个style风格样式,将背景设置为透明即可。
<!--Dialog将白色背景变透明--> <style name="Dialog" parent="android:style/Theme.Dialog"> <item name="android:background">@android:color/transparent</item> <item name="android:windowBackground">@android:color/transparent</item> <item name="android:windowNoTitle">true</item> </style>
此时我们再在CommonDialog中设置一个style样式,根据传入的样式来处理风格。
public Builder style(int resStyle) { this.resStyle = resStyle; return this; }
最后我们再写两个CommonDialog的构造方法,根据是否有传入style来调用不同父类。完成操作。
private CommonDialog(Builder builder) { super(builder.context); context = builder.context; cancelTouchout = builder.cancelTouchout; view = builder.view; } private CommonDialog(Builder builder, int resStyle) { super(builder.context, resStyle); context = builder.context; cancelTouchout = builder.cancelTouchout; view = builder.view; }
到此我们的整个代码就全部操作完毕。
使用
使用起来也非常简单,我们只需要创建一个CommonDialog.Builder根据不同的业务需求来添加不同操作即可。
CommonDialog build; //dialog弹窗 private void dialog(){ build = new CommonDialog.Builder(this) .view(R.layout.dialog)//设置弹窗的样式layout .style(R.style.Dialog) //设置主题,这里可以将背景设为透明,这样只显示你需要显示的dialog部分 .cancelTouchout(true) //设置点击dialog之外是否弹窗消失,true为消失,false为不消失 .setTitle(R.id.txt_title, "这是一个弹窗标题")//根据id来设置标题的显示文字 .setMessage(R.id.txt_message, "这是一个弹窗消息内容")//根据id来设置消息内容的显示文字 .addViewOnclick(R.id.txt_sure, new View.OnClickListener() {//处理确认点击事件 @Override public void onClick(View v) { Toast.makeText(MainActivity.this, "点击了确定按钮", Toast.LENGTH_SHORT).show(); build.dismiss(); } }) .addViewOnclick(R.id.txt_cancel, new View.OnClickListener() {//处理取消的点击事件 @Override public void onClick(View v) { Toast.makeText(MainActivity.this, "点击了取消按钮", Toast.LENGTH_SHORT).show(); build.dismiss(); } }).build(); build.show(); }
最后
更多Android进阶技术,面试资料系统整理分享,职业生涯规划,产品,思维,行业观察,谈天说地。可以加Android架构师群;701740775。
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Android 开发应该掌握的 Proguard 技巧
Proguard介绍 Proguard被人们熟知的是它的混淆功能,根据Proguard帮助文档的描述,Proguard可以对Java class 文件进行shrink,optimize,obfuscate和preveirfy。obfuscate(混淆)只是其中之一。简要的介绍下这四个功能: 压缩(Shrink): 检测和删除没有使用的类,字段,方法和特性 优化(Optimize): 分析和优化Java字节码 混淆(Obfuscate): 使用简短的无意义的名称,对类,字段和方法进行重命名 预检(Preveirfy): 用来对Java class进行预验证(预验证主要是针对JME开发来说的,Android中没有预验证过程,默认是关闭) 补充说明:根据proguard-android-optimize.txt对optimize的描述,在Android中使用该功能是有潜在风险的,并不能保证在所有版本的Dalvik虚拟机上正常运行,该选项默认是关闭的,如果开启,请做好全面的测试。在Android项目中,我们在相应module下的build.gradle文件中会看到 buildTypes { r...
- 下一篇
通过安装包重排布优化 Android 端启动性能
1. 前言 本章节我们将围绕《支付宝 App 构建优化解析》另启新系列,细分拆解客户端在“代码管理”、“证书管理”、“版本管理”、“构建打包”等维度的具体实现方案展开讨论,带领大家进一步了解支付宝在 App 构建模块下的持续优化。 本节将主要记录通过对支付宝 Android Apk 文件的重新布局,来改善 IO 性能的过程。 2. 背景 支付宝 App 在 Android 平台上,由于大量业务快速上线,Android 长尾机型等原因,造成启动阶段及部分核心链路上,性能体验不理想,进而影响用户的使用的感受。 从纯业务角度,可以通过优化 UI 布局,优化代码结构,优化 bundle 加载等方式,对性能体验有所改善。作为工程技术团队,按照传统思维来看,似乎无法对性能优化做多少贡献。经过一些方案调研后,我们尝试通过对编译产物的优化,干预构建流程,以提升 App 性能。 3. 原理 布局前后,Apk 中实际的文件并没有本质改变,只有位置发生了变化。那么为什么这样的调整会有性能造成影响?这个原理要追溯到 Linux 的文件系统机制。 如下图所示,Linux 底层文件系统中 VFS 上次 App 进...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Windows10,CentOS7,CentOS8安装Nodejs环境
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- CentOS8编译安装MySQL8.0.19
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- 2048小游戏-低调大师作品
- Docker安装Oracle12C,快速搭建Oracle学习环境
- SpringBoot2整合Redis,开启缓存,提高访问速度
- CentOS7安装Docker,走上虚拟化容器引擎之路