Android中的Dialog的使用以及自定义Dialog

在安卓开发中,我们会在某些特定的事件前面用来提示用户是否真的需要这样操作,避免因为用户误触而导致的一些不可逆的操作,而在处理这种事件
的一种方式就是用Dilaog来 让用户确定自己的操作。

Dilaog的布局分为上、中、下三个块,上为显示标题和图标的位置,中间显示的内容,下面显示的是操作的按钮。

官方给我们提供的AlertDialog 这个类,它不仅能创建带按钮的提示对话框,还可以生产带列表的对话框,总来的来说有以下四种情况:
1.带“确定”、“取消”,“中立”等几个按钮的提示框,其中按钮数量不固定,根据需要去添加。
2.带列表的对话框。
3.带单选列表项的对话框。
4.带多选列表项的对话框。

那么我们先来看*种情况:显示一个**常规**的对话框

new AlertDialog.Builder(this).setIcon(android.R.drawable.btn_star)
.setTitle(“这个是标题”).setMessage(“你有对象吗?”)
.setPositiveButton(“有”,new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,int which) {
Toast.makeText(MainActivity.this, “恭喜你”, Toast.LENGTH_SHORT).show();
dialog.dismiss();
}
})
.setNeutralButton(“保密”,new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,int which) {
Toast.makeText(MainActivity.this, “装逼,一看就是单身狗”, Toast.LENGTH_SHORT).show();
dialog.dismiss();
}
})
.setNegativeButton(“没有”,new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,int which) {
Toast.makeText(MainActivity.this, “那你还写个毛代码”, Toast.LENGTH_SHORT).show();
dialog.dismiss();
}
}).show();// show很关键

这样就弹出了一个基本的对话框,有三个按钮,有内容,有标题和标题图标。在这里如果你是5.0版本一下引用的是“android.app.AlertDialog”这个
包,那么三个按钮是weight为1:1:1的比例显示的。如果你引用的是“android.support.v7.app.AlertDialog”这个包的话,
那么两个确认的按钮在右边显示,中立的“保密”按钮会在左边显示。一般情况下我们只有两个按钮,我们首选v7包下的对话框显示,毕竟这是一个看脸的年代。

如果是5.0及以上版本都显示的是图2
%title插图%num

我们先来看第二种情况:显示一个带**列表**的对话框

final String itemContent[] = new String[]{“李宇春”,”王尼玛”,”罗玉凤”,”林志玲”};

new AlertDialog.Builder(this).setIcon(android.R.drawable.btn_star)
.setTitle(“你选对象的标准是什么?”).setItems(itemContent, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int i) {
Toast.makeText(MainActivity.this, “你喜欢”+itemContent[i], Toast.LENGTH_SHORT).show();
dialog.dismiss();
}
}).show();// show很关键

在这里需要说明的是对于dialog中内容的设置,如setMessage(),setItems(),setItemchoice()是有优先级的,如果你同时设置了三种,或者其中的两种,
如果有setMessage(),那么就只会显示你设置的message的内容,而另外设置的Items()或者ItemsChoice()中的内容不会显示,因为setMessage的优先级是*高的,
而且这三种显示内容的方式是并列的关系,就是只能选择一直方式展示对话框中间部分的内容。
%title插图%num

我们来看第三种情况:显示一个带**单选**的对话框

final String itemContent[] = new String[]{“李宇春”, “王尼玛”, “罗玉凤”, “林志玲”};
str = itemContent[0];//str为一个全局变量的字符串,用来在点击确定时候获取选中的值
new AlertDialog.Builder(this)
.setIcon(android.R.drawable.btn_star)
.setTitle(“你选对象的标准是什么?”).setSingleChoiceItems(itemContent, 0, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int i) {
str = itemContent[i];
}
}).setNegativeButton(“取消”, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int i) {
dialog.dismiss();
}
}).setPositiveButton(“确定”, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int i) {
Toast.makeText(MainActivity.this, “你喜欢” + str, Toast.LENGTH_SHORT).show();
dialog.dismiss();
}
})
.show();

 

我们来看第四种情况:显示一个带**单选**的对话框

final String itemContent[] = new String[]{“李宇春”, “王尼玛”, “罗玉凤”, “林志玲”};
final boolean checkedItems[] = new boolean[itemContent.length];//创建一个和可选项长度相同的数组记录选中项

new AlertDialog.Builder(this)
.setIcon(android.R.drawable.btn_star)
.setTitle(“你选对象的标准是什么?”).setMultiChoiceItems(itemContent, checkedItems, new DialogInterface.OnMultiChoiceClickListener() {
@Override
public void onClick(DialogInterface dialog, int i, boolean b) {
checkedItems[i] = b;
}
}).setNegativeButton(“取消”, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int i) {
dialog.dismiss();
}
}).setPositiveButton(“确定”, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int i) {
String str = getChoose(itemContent, checkedItems);
if (str.equals(“请至少选则一个项目”)) {
Toast.makeText(MainActivity.this, str, Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(MainActivity.this, str, Toast.LENGTH_SHORT).show();
dialog.dismiss();
}

}
})
.show();

private String getChoose(String[] itemContent, boolean[] checkedItems) {
String strChoose = “”;//接收选中的字符串
for (int i = 0; i < checkedItems.length; i++) {
if (checkedItems[i]) {//如果是选中则将其拼接到strChoose后
strChoose += TextUtils.concat(itemContent[i], “,”).toString();
}
}
//返回字符串前判断字符串长度是否大于0(即是否有选中的),有则返回选中的,没有则应该提示不能选中空的
if (strChoose.length() > 0) {
//去掉*末尾的逗号
strChoose = TextUtils.concat(“你选中了:”, strChoose.substring(0, strChoose.length() – 1)).toString();
} else {
strChoose = “请至少选则一个项目”;
}
return strChoose;
}
%title插图%num

我们用我们自己写的布局替换系统Dilaog的布局:

View dialogView = LayoutInflater.from(this).inflate(R.layout.my_dialog, null);//解析我们自己写的布局
final Dialog dialog = new AlertDialog.Builder(this).create();//创建一个dialog
dialog.show();//此处dialog应该先show然后再加载布局,否则会报错
dialog.setContentView(dialogView);
//初始化控件
ImageView mImage = (ImageView) dialogView.findViewById(R.id.dialog_title_image);
TextView mTitle = (TextView) dialogView.findViewById(R.id.dialog_title_content);
TextView mMessage = (TextView) dialogView.findViewById(R.id.dialog_message_text);
Button mCancelBtn = (Button) dialogView.findViewById(R.id.dialog_cancel_button);
Button mEnsureBtn = (Button) dialogView.findViewById(R.id.dialog_ensure_button);
mImage.setBackgroundResource(R.mipmap.ic_launcher);
mTitle.setText(“这是标题”);
mMessage.setText(“这是内容”);
mCancelBtn.setText(“取消”);
mEnsureBtn.setText(“确定”);
mCancelBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(MainActivity.this, “取消”, Toast.LENGTH_SHORT).show();
dialog.dismiss();
}
});
mEnsureBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(MainActivity.this, “确定”, Toast.LENGTH_SHORT).show();
dialog.dismiss();
}
});

布局文件的代码为:(xml名称为:my_dialog)
<?xml version=”1.0″ encoding=”utf-8″?>
<LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android”
android:layout_width=”match_parent”
android:layout_height=”match_parent”
android:orientation=”vertical”>

<LinearLayout
android:layout_width=”match_parent”
android:layout_height=”40dp”
android:orientation=”horizontal”>

<ImageView
android:id=”@+id/dialog_title_image”
android:layout_width=”30dp”
android:layout_height=”30dp”
android:layout_gravity=”center_vertical”
android:layout_marginLeft=”10dp” />

<TextView
android:id=”@+id/dialog_title_content”
android:layout_width=”wrap_content”
android:layout_height=”match_parent”
android:gravity=”center_vertical” />
</LinearLayout>

<TextView
android:id=”@+id/dialog_message_text”
android:layout_width=”match_parent”
android:layout_height=”wrap_content”
android:layout_margin=”10dp”
android:padding=”10dp” />

<LinearLayout
android:layout_width=”match_parent”
android:layout_height=”40dp”
android:orientation=”horizontal”>

<Button
android:id=”@+id/dialog_ensure_button”
android:layout_width=”0dp”
android:layout_height=”match_parent”
android:layout_weight=”1″ />

<Button
android:id=”@+id/dialog_cancel_button”
android:layout_width=”0dp”
android:layout_height=”match_parent”
android:layout_weight=”1″ />
</LinearLayout>

</LinearLayout>
%title插图%num

Android 自定义Dialog实现步骤及封装

在项目中,我们会遇到各种各样的界面需求,比如对话框和选择框,都是会配合具体项目的UI界面来做,而不是说用自带的弹出框。比如下面在登录界面的二个对话框效果。都是我在做具体项目中所要求实现的:

1.输入有误时弹出的对话框

%title插图%num

2.选择角色登录时的对话框

%title插图%num

这里倒不是说自定义Dialog的教程,因为自定义Dialog大家基本都会。只是我在登录界面写了这二个Dialog之后,我就觉得好烦,然后决定封装了一个类,因为后面不同界面还有很多不同的弹框。为后期节省时间。倒不是说我这个封装类写的有多好,只是写出来,大家可以看下,然后哪里不好可以跟我提下意见。

让我们一步步来看是如何自定这个自定义对话框及如何来进行封装自己的自定义Dialog工具类。我就按照实际项目中,我的开发步骤来说明。

如何生成这种自定义对话框

实际开发中,我看到了*个效果图中的对话框,于是我马上大手一挥,自定义了一个类ErrorDialog,继承了Dialog。

  1. public class ErrorDialog extends Dialog{
  2. public ErrorDialog(Context context) {
  3. super(context);
  4. }
  5. public ErrorDialog(Context context, int themeResId) {
  6. super(context, themeResId);
  7. }
  8. protected ErrorDialog(Context context, boolean cancelable
  9. , OnCancelListener cancelListener) {
  10. super(context, cancelable, cancelListener);
  11. }
  12. }

我们可以看到有三个构造函数,这三个构造函数不是一定要都实现,但至少要实现一个构造函数。我们来具体说明下各个构造函数的作用。

  1. ErrorDialog(Context context):
    单纯传入Context,用的比较多。在代码中通过new ErrorDialog(context);来获得Dialog的实例,然后使用show()方法进行展现。

  2. ErrorDialog(Context context, int themeResId)
    大家可以看到比*个构造函数多了一个themeResId,就是我们可以传入一个主题值,比如R.style.XXX。然后构造函数中会调用super(context, themeResId);等会生成的Dialog就会带有这个R.style.XXX所设置的效果。

  3. ErrorDialog(Context context, boolean cancelable, OnCancelListener cancelListener):
    大家都知道,对话框弹出来后,默认情况下,我们在屏幕上触摸对话框以外的屏幕的界面,对话框会默认消失。我们平时做对话框的时候一般都是让这个对话框点击外面的其他界面地方的时候不让对话框消失,我们一般在代码中会这么写:setCanceledOnTouchOutside(false);。为什么我提这个,没错,这个构造函数里面的那个boolean cancelable控制的就是这个功能,<1>当传入为true的时候,就是可以点击外面来让对话框消失,然后消失的时候会调用后面第三个参数的cancelListener这个listener里面的方法。我们可以在里面做相应的监听事件。<2>当传入false。那么点击外面区域,这个对话框也就不会消失,而且后面的那个listener也不会被调用。

好了,构造函数说好后。我们来具体看如何生成界面Dialog界面。于是我大手再次一挥。写了个对话框所需要的效果的Layout:

  1. <?xml version=”1.0″ encoding=”utf-8″?>
  2. <LinearLayout xmlns:android=“http://schemas.android.com/apk/res/android”
  3. android:layout_width=“200dp”
  4. android:layout_height=“250dp”
  5. android:background=“@drawable/background_loginerror”
  6. android:gravity=“center_horizontal”
  7. android:orientation=“vertical”>
  8. <ImageView
  9. android:layout_marginTop=“30dp”
  10. android:layout_width=“80dp”
  11. android:layout_height=“80dp”
  12. android:src=“@drawable/gong”
  13. />
  14. <TextView
  15. android:layout_marginTop=“20dp”
  16. android:layout_width=“wrap_content”
  17. android:layout_height=“wrap_content”
  18. android:text=“您输入的内容有误”
  19. />
  20. <Button
  21. android:id=“@+id/btn_cancel”
  22. android:layout_marginTop=“20dp”
  23. android:layout_width=“120dp”
  24. android:layout_height=“40dp”
  25. android:text=“@string/confirm”
  26. android:background=“@drawable/background_loginbtn”
  27. />
  28. </LinearLayout>

效果如下图所示(那个感叹号的图片我这边因为切图没有的问题。临时换成了工商的图标。反正不影响我们开发教程):

%title插图%num

然后我们在自定义的ErrorDialog中写oncreate方法:

  1. @Override
  2. protected void onCreate(Bundle savedInstanceState) {
  3. super.onCreate(savedInstanceState);
  4. View view = View.inflate(context,R.layout.dialog_loginerror,null);
  5. setContentView(view);
  6. }

然后这时候我以为就跟继承Activity一样。变成了我自定义的布局界面。然后我满心欢喜的在Activity中调用了:
ErrorDialog dialog = new ErrorDialog(this); dialog.show();

%title插图%num

WTF!!
这是逗我吗,我的自定义布局明明是个圆角啊。怎么变成了个长方形。
所以我就把我们自定义布局的背景色换成其黑色。看下效果:

%title插图%num

这下首先知道了。我们其实自定义的layout类似于是盖在了底部白色的背景上面,恰好我们的自定义布局也是白色。所以我们现在首先要把底部的那个白色背景变为透明,那样,就会出现我们自定义布局的圆角了

那我们下一步的目的就是要设置Dialog自定义的theme。

把Dialog自带的白色背景色改为透明即可,很简单。百度一搜一大把。哈哈。其实说到底就是继承android:style/Theme.Dialog主题,然后再覆写其中的几个相关属性,比如背景设置为透明,去除自带的title等属性。

(我在网上看的时候,网上有人推荐Android4.0后,不要使用Theme.Dialog。改为使用Theme.Holo.DialogWhenLarge。
Android4: 请放弃使用Theme.Dialog
当然对我们这个自定义布局需求,继承哪个都能实现效果。就看大家怎么选择了。
)

好,那我们就自定义继承Theme.Dialog:

  1. <style name=“Dialog” parent=“android:style/Theme.Dialog”>
  2. <item name=“android:background”>@android:color/transparent</item>
  3. <item name=“android:windowBackground”>@android:color/transparent</item>
  4. <item name=“android:windowNoTitle”>true</item>
  5. </style>

(如果有其他需求,再覆写其他的属性即可,本例中就只需要改这三个)

好了。然后在上面我们介绍过的生成Dialog实例中的第二个构造函数,是传入Theme。我们调用:

  1. ErrorDialog dialog = new ErrorDialog(this,R.style.Dialog);
  2. dialog.show();

然后我们看到效果了:

 

%title插图%num

 

起码形状变成我们的自定义布局的形状了。哈哈。但是这个Dialog大小和我们的自定义布局大小不同。

下一步要处理Dialog呈现的自定义布局的大小

还是老样子,百度一搜一大把,好吧。我实在是太懒了。(不服气我懒的话,过来打我哈。O(∩_∩)O)

  1. Window win = getWindow();
  2. WindowManager.LayoutParams lp = win.getAttributes();
  3. lp.gravity = Gravity.CENTER;
  4. lp.height = DensityUtil.dip2px(context,250);
  5. lp.width = DensityUtil.dip2px(context,200);
  6. win.setAttributes(lp);

我来解释下,因为上面我们自定义布局的大小就是

  1. android:layout_width=“200dp”
  2. android:layout_height=“250dp”

所以我们这里也设置这个对话框的大小也设置为相同大小,这样就等于显示出我们自定义布局大小。这里因为高和宽改为我们自己自定义布局大小,所以lp.gravity = Gravity.CENTER;这句也可以不写,因为反正是正好完全填充。


所以我们当前的自定义Dialog代码变为:

  1. @Override
  2. protected void onCreate(Bundle savedInstanceState) {
  3. super.onCreate(savedInstanceState);
  4. View view = View.inflate(context,R.layout.dialog_loginerror,null);
  5. setContentView(view);
  6. Window win = getWindow();
  7. WindowManager.LayoutParams lp = win.getAttributes();
  8. lp.height = DensityUtil.dip2px(context,250);
  9. lp.width = DensityUtil.dip2px(context,200);
  10. win.setAttributes(lp);
  11. }
点击事件
  1. 一般我们项目中跳出了对话框,点击对话框外面的区域,是不能默认让对话框消失的。所以我们需要添加setCanceledOnTouchOutside(false);
  2. 自定义布局上面的按钮点击事件的添加很简单,因为上面已经拿到了自定义布局的view的对象。比如我们上面的自定义布局有个<确定>按钮,我们点击按钮让对话框消失。我们只需要:
  1. view.findViewById(R.id.btn_cancel).setOnClickListener(new Button.OnClickListener() {
  2. @Override
  3. public void onClick(View view) {
  4. dismiss();
  5. }
  6. });

*终的自定义ErrorDialog代码:

  1. public class ErrorDialog extends Dialog {
  2. public Context context;
  3. public ErrorDialog(Context context) {
  4. super(context);
  5. this.context = context;
  6. }
  7. public ErrorDialog(Context context, int theme) {
  8. super(context, theme);
  9. this.context = context;
  10. }
  11. public ErrorDialog(Context context, boolean cancelable, OnCancelListener cancelListener) {
  12. super(context, cancelable, cancelListener);
  13. this.context = context;
  14. }
  15. @Override
  16. protected void onCreate(Bundle savedInstanceState) {
  17. super.onCreate(savedInstanceState);
  18. View view = View.inflate(context, R.layout.dialog_loginerror, null);
  19. setContentView(view);
  20. setCanceledOnTouchOutside(false);
  21. Window win = getWindow();
  22. WindowManager.LayoutParams lp = win.getAttributes();
  23. lp.height = DensityUtil.dip2px(context, 250);
  24. lp.width = DensityUtil.dip2px(context, 200);
  25. win.setAttributes(lp);
  26. view.findViewById(R.id.btn_cancel).setOnClickListener(new Button.OnClickListener() {
  27. @Override
  28. public void onClick(View view) {
  29. dismiss();
  30. }
  31. });
  32. }
  33. }

*后生成的界面如下:

%title插图%num


—————————————-本文正文,封装君正式登场—————————————————–

上面只是介绍了自定义Dialog的基本知识。而且这个ErrorDialog只能用于*个效果图所需的Dialog需求,然后比如我们要第二个效果图的需求。然后自己再写一个ChangeDialog???一个项目有5种不同的界面Dialog。我要写5个自定义Dialog类???答案当然是NO,NO,NO。

我们来看下,上面我们完成ErrorDialog的时候,到底需要哪些东西,才能*后完成一个自定义Dialog。

  1. Context
  2. R.style.XXXX
  3. R.layout.XXXX
  4. setCanceledOnTouchOutside(XXXX);是否允许点击外部区域来让Dialog消失
  5. WindowManager.LayoutParams对象类的height和width。
  6. 自定义布局上各个View的点击事件

基本是上述五个需求。(额外需求,大家就在这基础上封装好的类中添加自己的需求即可)

我们也是模仿Dialog建立的Builder模式,自己写个封装类。
(Builder模式的介绍和用Android Studio插件来快速自动生成代码,大家可以来看下我已经写得文章:经典Builder/变种Builder模式及自动化生成代码插件)

我先上代码再来进行查看:

  1. public class CustomDialog extends Dialog {
  2. private Context context;
  3. private int height, width;
  4. private boolean cancelTouchout;
  5. private View view;
  6. private CustomDialog(Builder builder) {
  7. super(builder.context);
  8. context = builder.context;
  9. height = builder.height;
  10. width = builder.width;
  11. cancelTouchout = builder.cancelTouchout;
  12. view = builder.view;
  13. }
  14. private CustomDialog(Builder builder, int resStyle) {
  15. super(builder.context, resStyle);
  16. context = builder.context;
  17. height = builder.height;
  18. width = builder.width;
  19. cancelTouchout = builder.cancelTouchout;
  20. view = builder.view;
  21. }
  22. @Override
  23. protected void onCreate(Bundle savedInstanceState) {
  24. super.onCreate(savedInstanceState);
  25. setContentView(view);
  26. setCanceledOnTouchOutside(cancelTouchout);
  27. Window win = getWindow();
  28. WindowManager.LayoutParams lp = win.getAttributes();
  29. lp.gravity = Gravity.CENTER;
  30. lp.height = height;
  31. lp.width = width;
  32. win.setAttributes(lp);
  33. }
  34. public static final class Builder {
  35. private Context context;
  36. private int height, width;
  37. private boolean cancelTouchout;
  38. private View view;
  39. private int resStyle = –1;
  40. public Builder(Context context) {
  41. this.context = context;
  42. }
  43. public Builder view(int resView) {
  44. view = LayoutInflater.from(context).inflate(resView, null);
  45. return this;
  46. }
  47. public Builder heightpx(int val) {
  48. height = val;
  49. return this;
  50. }
  51. public Builder widthpx(int val) {
  52. width = val;
  53. return this;
  54. }
  55. public Builder heightdp(int val) {
  56. height = DensityUtil.dip2px(context, val);
  57. return this;
  58. }
  59. public Builder widthdp(int val) {
  60. width = DensityUtil.dip2px(context, val);
  61. return this;
  62. }
  63. public Builder heightDimenRes(int dimenRes) {
  64. height = context.getResources().getDimensionPixelOffset(dimenRes);
  65. return this;
  66. }
  67. public Builder widthDimenRes(int dimenRes) {
  68. width = context.getResources().getDimensionPixelOffset(dimenRes);
  69. return this;
  70. }
  71. public Builder style(int resStyle) {
  72. this.resStyle = resStyle;
  73. return this;
  74. }
  75. public Builder cancelTouchout(boolean val) {
  76. cancelTouchout = val;
  77. return this;
  78. }
  79. public Builder addViewOnclick(int viewRes,View.OnClickListener listener){
  80. view.findViewById(viewRes).setOnClickListener(listener);
  81. return this;
  82. }
  83. public CustomDialog build() {
  84. if (resStyle != –1) {
  85. return new CustomDialog(this, resStyle);
  86. } else {
  87. return new CustomDialog(this);
  88. }
  89. }
  90. }
  91. }

我这边的Builder中对height和width写了三种方式,比如直接写入px的值就调用heightpx(),如果直接写入dp值,就调用heightdp()。不过*多的应该还是调用heightDimenRes()方法。因为一般我们在写自定义layout布局的时候,height和width的数值肯定是去dimen.xml中获取。所以我们在代码中生成这个自定义对话框的时候,也就直接调用了heightDimenRes(R.dimen.XXX)。这样。我们什么时候需求变了,说这个对话框的大小要进行更改,我们不需要更改代码,只需要在demen.xml中将数值修改即可。

然后我们再来写上面的ErrorDialog:

  1. CustomDialog.Builder builder = new CustomDialog.Builder(this);
  2. dialog =
  3. builder.cancelTouchout(false)
  4. .view(R.layout.dialog_loginerror)
  5. .heightDimenRes(R.dimen.dialog_loginerror_height)
  6. .widthDimenRes(R.dimen.dialog_loginerror_width)
  7. .style(R.style.Dialog)
  8. .addViewOnclick(R.id.btn_cancel,new View.OnClickListener() {
  9. @Override
  10. public void onClick(View view) {
  11. dialog.dismiss();
  12. }
  13. })
  14. .build();
  15. dialog.show();

真是简单!!!!!

好了我们现在要第二个效果图的对话框了。比如我现在为了简单。就做了个简单的自定义Layout。

%title插图%num

然后点击“经办人”,“审批人”,“确认”按钮,有不同点击效果。
生成这个对话框代码如下:

  1. View.OnClickListener listener = new View.OnClickListener() {
  2. @Override
  3. public void onClick(View view) {
  4. switch (view.getId()){
  5. case R.id.jbperson :
  6. Toast.makeText(aty, “选择经办人按钮”, Toast.LENGTH_SHORT).show();
  7. break;
  8. case R.id.spperson:
  9. Toast.makeText(aty, “选择审批人按钮”, Toast.LENGTH_SHORT).show();
  10. break;
  11. case R.id.confirmbtn:
  12. Toast.makeText(aty, “点击确定按钮”, Toast.LENGTH_SHORT).show();
  13. break;
  14. }
  15. }
  16. };
  17. CustomDialog.Builder builder = new CustomDialog.Builder(this);
  18. CustomDialog dialog = builder
  19. .style(R.style.Dialog)
  20. .heightDimenRes(R.dimen.dilog_identitychange_height)
  21. .widthDimenRes(R.dimen.dilog_identitychange_width)
  22. .cancelTouchout(false)
  23. .view(R.layout.dialog_identitychange)
  24. .addViewOnclick(R.id.jbperson,listener)
  25. .addViewOnclick(R.id.spperson,listener)
  26. .addViewOnclick(R.id.confirmbtn,listener)
  27. .build();
  28. dialog.show();

 

真是简单!!!!!!!哈哈。当然我只是做了简单的封装。大家可以提出不同的意见。

设置 Dialog 不显示标题的常用方法

1、通过dialog的window窗口调用requestWindowFeature(int featureId)方法

getWindow().requestFeature(Window.FEATURE_NO_TITLE);

注意需要在 Dialog 中的 setContentView( ) 方法之前调用。

2、通过自定义一个style,添加 <item name=”android:windowNoTitle”>true</item> ,或者直接设置该 style 的 parent 为一个已经包含了 NoTitle 属性的样式,然后在创建 Dialog 实例时使用该样式作为 Theme。

Dialog(@NonNull Context context, @StyleRes int themeResId)

自定义Dialog所遇到的问题总结

自定义Dialog所遇到的问题总结
1. 在extents Dialog 后,对话框左右两边出现大概10dp的margin,通过自定义其style无效后的解决办法
解决方法:
Window window = dialog.getWindow();
WindowManager.LayoutParams params =
window.getAttributes();
params.width = WindowManager.LayoutParams.MATCH_PARENT;
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
params.gravity =Gravity.FILL_HORIZONTAL;
window.setAttributes(params);

说明:主要代码为
params.gravity =Gravity.FILL_HORIZONTAL;

2. extends Dialog 与 extends AlertDialog 引发的问题:前者可以调取软键盘,后者不起作用,这里写一下分析过程,问题虽然还没找到原因。
注意此问题都是通过自定义其style实现。

过程:
1.从extentds AlertDialog 开始向下追踪

public class CustomBottomDialog extends AlertDialog {
public CustomBottomDialog(Context context, int themeResId) {
super(context, themeResId);
}
}

protected AlertDialog(Context context, @StyleRes int themeResId) {
this(context, themeResId, true);
}

AlertDialog(Context context, @StyleRes int themeResId, boolean createContextThemeWrapper) {
super(context, createContextThemeWrapper ? resolveDialogTheme(context, themeResId) : 0,
createContextThemeWrapper);

mWindow.alwaysReadCloseOnTouchAttr();
mAlert = AlertController.create(getContext(), this, getWindow());
}
}

static @StyleRes int resolveDialogTheme(Context context, @StyleRes int themeResId) {
if (themeResId == THEME_TRADITIONAL) {
return R.style.Theme_Dialog_Alert;
} else if (themeResId == THEME_HOLO_DARK) {
return R.style.Theme_Holo_Dialog_Alert;
} else if (themeResId == THEME_HOLO_LIGHT) {
return R.style.Theme_Holo_Light_Dialog_Alert;
} else if (themeResId == THEME_DEVICE_DEFAULT_DARK) {
return R.style.Theme_DeviceDefault_Dialog_Alert;
} else if (themeResId == THEME_DEVICE_DEFAULT_LIGHT) {
return R.style.Theme_DeviceDefault_Light_Dialog_Alert;
} else if (ResourceId.isValid(themeResId)) {
// start of real resource IDs.
return themeResId;
} else {
final TypedValue outValue = new TypedValue();
context.getTheme().resolveAttribute(R.attr.alertDialogTheme, outValue, true);
return outValue.resourceId;
}
}

Dialog(@NonNull Context context, @StyleRes int themeResId, boolean createContextThemeWrapper) {
if (createContextThemeWrapper) {
if (themeResId == ResourceId.ID_NULL) {
final TypedValue outValue = new TypedValue();
context.getTheme().resolveAttribute(R.attr.dialogTheme, outValue, true);
themeResId = outValue.resourceId;
}
mContext = new ContextThemeWrapper(context, themeResId);
} else {
mContext = context;
}
}

如果extends Dialog 直接到*有一步,本质上都一样。