在android中有时候我们不会满足于原生的控件,根据我们的需要,我们可能会需要自己的AlertDialog,例如QQ中的提示对话框如下:
—————————————————————————————
如何实现上面的效果呢?
先看我们自定义的效果如下:
先说一下大概步骤:
1. 自定义layout布局文件,这就是我们看到的dialog的整体外观;
2. 在res/values/styles.xml中创建我们自定义dialog需要的样式;
3. 创建自定义的dialog类继承dialog,完成相关代码即可;
4. 在需要使用的地方,使用自定义的dialog即可;
代码如下:
1.自定义布局文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="300dp"
android:layout_height="wrap_content">
<!--标题-->
<TextView
android:id="@+id/tv_title"
android:layout_width="match_parent"
android:layout_height="40dp"
android:gravity="center|bottom"
android:text="删除好友"
android:textSize="18sp"
android:textStyle="bold"
android:textColor="#000000"/>
<!--内容-->
<TextView
android:id="@+id/tv_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="20dp"
android:gravity="center_vertical"
android:text=""
android:textColor="#000000"/>
<!--水平分割线-->
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/colorLine"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<!--按钮1-->
<Button
android:id="@+id/btn_cancel"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="取消"
android:textColor="@color/colorText"
android:textSize="16sp"
android:background="@drawable/shape_left_button"/>
<!--两个按钮间的垂直分割线-->
<View
android:layout_width="1dp"
android:layout_height="match_parent"
android:background="@color/colorLine"/>
<!--按钮2-->
<Button
android:id="@+id/btn_confirm"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="删除"
android:textColor="@color/colorText"
android:textSize="16sp"
android:background="@drawable/shape_right_button"/>
</LinearLayout>
</LinearLayout>
关键点是我么要设计两个按钮的按压状态,因此需要自己定义selector文件。我们注意:左边按钮的左下角是圆角,我们此时定义为15px,故左边按钮如下定义:(右边按钮同理即可)
*shape_left_button.xml 文件:*
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!--按压时-->
<item android:state_pressed="true" android:drawable="@drawable/shape_left"/>
<!--默认状态下-->
<item android:drawable="@drawable/shape_left_no"/>
</selector>
*shape_left.xml*
<?xml version="1.0" encoding="utf-8"?>
<!--按压状态-->
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:bottomLeftRadius="15px"/>
<!--改变背景颜色-->
<solid android:color="@color/colorLine"/>
</shape>
*shape_left_no.xml*
<?xml version="1.0" encoding="utf-8"?>
<!--未按压状态-->
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:bottomLeftRadius="15px"/>
</shape>
2.styles样式
<style name="MyDialog" parent="android:style/Theme.Dialog">
<!--dialog使用自己定义的背景-->
<item name="android:windowBackground">@drawable/dialog</item>
<!--dialog是否消除标题栏,默认是false,不消除的话,会占用一块空间-->
<item name="android:windowNoTitle">true</item>
<!--dialog是否浮动在activity上,默认是true,若为false话不会浮动在activity上-->
<item name="android:windowIsFloating">true</item>
<!--dialog的后面的activity是否显示灰色,默认是true-->
<item name="android:backgroundDimEnabled">true</item>
</style>
dialog的自定义背景如下:
*dialog.xml*
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<!--圆角为15px-->
<corners android:radius="15px"/>
<!--颜色为白色-->
<solid android:color="@color/white"/>
</shape>
3.自定义MyDialog继承Dialog
主要思想是模仿原生的Dialog,使用静态内部类Builder来管理各种组件,并使用回调函数来进行事件的处理。(回调函数可以参考上一篇文章)
package space.wanhu.app_0518;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
/**
* Created by Bingbing on 2016/5/18.
* 自己定制dialog,按照原生dialog的基本方式
*/
public class MyDialog extends Dialog {
public MyDialog(Context context, int theme) {
super(context, theme);
}
/**
* dialog的助手类
*/
public static class Builder{
//获取需要自定义的组件
private String tv_title,tv_content; //标题和内容
private String btn_cancel,btn_confirm;//两种按钮的内容
private DialogInterface.OnClickListener cancelListener,confirmListener;//回调接口对象
private Context context;//上下文对象
public Builder(Context context){
this.context = context;
}
/**
* 直接使用字符串来设置标题
*/
public Builder setTitle(String title){
this.tv_title = title;
return this;
}
/**
* 使用资源文件设置标题
*/
public Builder setTitle(int id){
this.tv_title = (String) context.getText(id);
return this;
}
/**
* 使用字符串设置dialog的提示内容
*/
public Builder setContent(String content){
this.tv_content = content;
return this;
}
/**
* 使用资源文件来设置dialog的内容
*/
public Builder setContent(int id){
this.tv_content = (String) context.getText(id);
return this;
}
/**
* 设置左边按钮的文字提示和回调函数
*/
public Builder setCancelButton(String cancel,DialogInterface.OnClickListener cancelListener){
this.btn_cancel = cancel;
this.cancelListener = cancelListener;
return this;
}
/**
* 使用资源文件设置左边按钮的挑剔提示和回调函数
*/
public Builder setCancelButton(int id,DialogInterface.OnClickListener cancelListener){
this.btn_cancel = (String) context.getText(id);
this.cancelListener = cancelListener;
return this;
}
/**
* 设置右边确定按钮的文字提示和回调函数
*/
public Builder setConfirmButton(String confirm,DialogInterface.OnClickListener confirmListener){
this.btn_confirm = confirm;
this.confirmListener = confirmListener;
return this;
}
/**
* 使用资源文件来设置确定按钮的文字提示和回调函数
*/
public Builder setConfirmButton(int id,DialogInterface.OnClickListener confirmListener){
this.btn_confirm = (String) context.getText(id);
this.confirmListener = confirmListener;
return this;
}
/**
* 在create方法中完成初始化和事件的注册
*/
public MyDialog create(){
//获取自定义的布局文件
View viewRoot = LayoutInflater.from(context).inflate(R.layout.dialog_layout,null);
//获取自定义dialog实例,并引入自定义的样式
final MyDialog dialog = new MyDialog(context,R.style.MyDialog);
//设置标题显示
if(tv_title != null){
((TextView)viewRoot.findViewById(R.id.tv_title)).setText(tv_title);
}
//设置显示的内容
if(tv_content != null){
((TextView)viewRoot.findViewById(R.id.tv_content)).setText(tv_content);
}
//设置左边按钮的文本和实现回调函数
if(btn_cancel != null){
Button button_cancel = (Button) viewRoot.findViewById(R.id.btn_cancel);
button_cancel.setText(btn_cancel);
if(cancelListener != null) {
button_cancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
cancelListener.onClick(dialog, DialogInterface.BUTTON_NEGATIVE);
}
});
}
}else {
((Button)viewRoot.findViewById(R.id.btn_cancel)).setVisibility(View.GONE);
}
//设置确定按钮的文本和实现回调函数
if(btn_confirm != null){
Button button_confirm = (Button) viewRoot.findViewById(R.id.btn_confirm);
button_confirm.setText(btn_confirm);
if(confirmListener != null){
button_confirm.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
confirmListener.onClick(dialog,DialogInterface.BUTTON_NEGATIVE);
}
});
}
}else {
((Button)viewRoot.findViewById(R.id.btn_confirm)).setVisibility(View.GONE);
}
dialog.setContentView(viewRoot);
return dialog;
}
}
}
4. 使用自己定义的MyDialog,方法和原生的基本类似:
package space.wanhu.app_0518;
import android.content.Context;
import android.content.DialogInterface;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private Context context;
private MyDialog dialog;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
context = this;
//启动原始的dialog
findViewById(R.id.btn_ori).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
initOriDialog();
}
});
//启动自定义dialog
findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
initDialog();
}
});
}
/**
* 初始化自定义的dialog
*/
private void initDialog(){
MyDialog.Builder builder = new MyDialog.Builder(context);
builder.setTitle("删除");
builder.setContent(R.string.tv_content);
builder.setCancelButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
builder.setConfirmButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(context,"您点击了确定!",Toast.LENGTH_SHORT).show();
}
});
dialog = builder.create();
dialog.setCanceledOnTouchOutside(false);
dialog.show();
}
/**
* 初始化原始的dialog
*/
private void initOriDialog(){
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle("删除好友");
builder.setMessage("同时会将我从对方的列表中删除,且屏蔽对方的临时会话,不再接受此人\n" +
"的消息同时会将我从对方的列表中删除.");
builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(context,"您点击了取消",Toast.LENGTH_SHORT).show();
}
});
builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(context,"您点击了确定",Toast.LENGTH_SHORT).show();
}
});
builder.create().show();
}
}
过程结束了,只要理解了基本的原理,我们就可以定义自己想要的Dialog了。
参考文档:
1. Android自定义对话框Dialog
2. 关于自定义Dialog的那些事
3. Android自定义Dialog