动手造轮子——用Builder模式撸一个通用版本的Dialog 前言

简介:  在Android开发中我们常常需要使用Dialog来处理一些弹窗操作。虽然Android系统本身为我们封装了一个自带的弹窗Dialog,但是由于Android操作系统的不同,导致了每个手机弹窗页面的不同,以至于我们很难用系统的去统一样式。

动手造轮子用Builder模式撸一个通用版本的Dialog 前言

 

在Android开发中我们常常需要使用Dialog来处理一些弹窗操作。虽然Android系统本身为我们封装了一个自带的弹窗Dialog,但是由于Android操作系统的不同,导致了每个手机弹窗页面的不同,以至于我们很难用系统的去统一样式。并且UI会觉得系统的弹窗过于丑陋,希望自己来做一个于是我们便需要自己来处理一个Dialog弹窗。今天叫大家利用Builder构造者模式自己来封装一个弹窗Dialog。

需求分析

首先确定一下,弹窗我们需要哪些功能?

  1. 需要可以自己自定义样式。因为每个弹窗会根据逻辑和需求的不同拥有不同的样式。例如有些弹窗有title标题,有些只有message提示;有些有确定和取消按钮,有些又只有一个确定按钮。我们必须用一套代码来加载不同的样式才行。
  2. 设置title或者message的内容。这里可以根据传入的不同id设置不同文字内容。
  3. 设置按钮的点击事件
  4. 设置是否需要点击弹窗外部使得弹窗消失。

开始操作

分析完了需求之后我们便可以根据需求来撸代码了。

首先我们写一个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旁边还有一些白色的存在。正是因为这些白色,导致了我们无论如何设置弹窗宽度都显示的是原来的大小。如果你要设置为圆角,那更是不太可能。

动手造轮子用Builder模式撸一个通用版本的Dialog 前言

 

那该如何处理这种情况?其实很简单,我们仅仅需要设置一下将弹窗风格的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;
 }

动手造轮子用Builder模式撸一个通用版本的Dialog 前言

 

到此我们的整个代码就全部操作完毕。

使用

使用起来也非常简单,我们只需要创建一个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。

相关文章
|
6天前
|
Web App开发 数据采集 Java
《手把手教你》系列技巧篇(三十)-java+ selenium自动化测试- Actions的相关操作下篇(详解教程)
【4月更文挑战第22天】本文介绍了在测试过程中可能会用到的两个功能:Actions类中的拖拽操作和划取字段操作。拖拽操作包括基本讲解、项目实战、代码设计和参考代码,涉及到鼠标按住元素并将其拖动到另一个元素上或指定位置。划取字段操作则介绍了如何在一段文字中随机选取一部分,包括项目实战、代码设计和参考代码。此外,文章还提到了滑动验证的实现,并提供了相关的代码示例。
41 2
|
6天前
|
测试技术 Android开发
快速上手App自动化测试利器,Toast原理解析及操作实例
`Toast`是Android中的轻量级通知,短暂显示在屏幕任意位置,1-2秒后自动消失,不获取焦点且不可点击。Appium通过uiautomator2在控件树中处理Toast。在测试中,可设置隐式等待,利用XPath或Accessibility ID定位Toast元素进行检测和验证。示例代码展示了如何初始化driver,点击触发Toast,以及如何定位并读取Toast文本。
28 3
|
6天前
|
缓存
Quarto 入门教程 (3):细节设置
Quarto 入门教程 (3):细节设置
92 1
|
前端开发
前端知识学习案例7vs code-安装扩展
前端知识学习案例7vs code-安装扩展
46 0
前端知识学习案例7vs code-安装扩展
|
测试技术 Python
【第五篇-完结篇】XiaoZaiMultiAutoAiDevices之改造扩展
在前面系列文章中有讲到,使用configparser,ini格式的文件作为配置文件,在新增或者删除其中的值时,会丢失所有注释,所以在框架源码注释中我有写到,如果对这方面比较介意或者是有需求的话,可以进行更改配置文件。
109 0
|
C# 图形学
egret连连看项目实战之三(解析配置表)
egret连连看项目实战之三(解析配置表)
egret连连看项目实战之三(解析配置表)
|
存储 前端开发 数据库
Android MVVM框架使用(十一)(功能开发)记事本
Android MVVM框架使用(十一)(功能开发)记事本
485 0
Android MVVM框架使用(十一)(功能开发)记事本
|
前端开发 小程序 IDE
「趣学前端」给不懂技术的朋友简单演示,代码是怎么被编写出来的
我身边不乏非程序员的朋友,对我的工作多多少少带点好奇心。突发奇想,准备了一个小功能,简单演示前端日常开发中的代码是怎么被编写出来的。
127 1
|
资源调度 前端开发
阅读源码入门实践系列之 element ui(1)
阅读源码入门实践系列之 element ui(1)
132 1
|
vr&ar 图形学 索引
【Unity3D 灵巧小知识点】 ☀️ | Unity中如何使用代码切换场景
Unity 小科普 老规矩,先介绍一下 Unity 的科普小知识: Unity是 实时3D互动内容创作和运营平台 。 包括游戏开发、美术、建筑、汽车设计、影视在内的所有创作者,借助 Unity 将创意变成现实。 Unity 平台提供一整套完善的软件解决方案,可用于创作、运营和变现任何实时互动的2D和3D内容,支持平台包括手机、平板电脑、PC、游戏主机、增强现实和虚拟现实设备。 也可以简单把 Unity 理解为一个游戏引擎,可以用来专业制作游戏!
【Unity3D 灵巧小知识点】 ☀️ | Unity中如何使用代码切换场景