为了账号安全,请及时绑定邮箱和手机立即绑定

自定义对话框Dialog的几种方式

标签:
Android

自定义继承Dialog控件对话框

自定义控件

接下来我就以一个简单风格的自定义Dialog来讲讲自定义dialog的一般步骤和原理

第一步: 给Dialog设置一个风格主题(基本都是用这个主题)无边框全透明背景

<!--自定义dialog背景全透明无边框theme -->  
    <style name="MyDialog" parent="android:style/Theme.Dialog">  
        <!--背景颜色及和透明程度-->  
        <item name="android:windowBackground">@android:color/transparent</item>  
        <!--是否去除标题 -->  
        <item name="android:windowNoTitle">true</item>  
        <!--是否去除边框-->  
        <item name="android:windowFrame">@null</item>  
        <!--是否浮现在activity之上-->  
        <item name="android:windowIsFloating">true</item>  
        <!--是否模糊-->  
        <item name="android:backgroundDimEnabled">false</item>  
    </style>

第二步:给自定的Dialog设置自定义的 xml界面,我这里只是示范,你可以使用单选,多选,3个按钮,4个按钮等等,格式各样的自定义XML,我这里就定义了 标题title,信息message,还有一个确定按钮和取消按钮,如下:

<?xml version="1.0" encoding="utf-8"?>  
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent"  
    android:background="#11ffffff">  

    <LinearLayout  
        android:layout_width="260dp"  
        android:layout_height="wrap_content"  
        android:layout_centerInParent="true"  
        android:background="@drawable/free_dialog_bg"  
        android:orientation="vertical">  

        <TextView  
            android:id="@+id/title"  
            android:layout_width="wrap_content"  
            android:layout_height="wrap_content"  
            android:layout_gravity="center"  
            android:layout_margin="15dp"  
            android:gravity="center"  
            android:text="消息提示"  
            android:textColor="#38ADFF"  
            android:textSize="16sp" />  

        <TextView  
            android:id="@+id/message"  
            android:layout_width="wrap_content"  
            android:layout_height="wrap_content"  
            android:layout_marginLeft="20dp"  
            android:layout_marginRight="20dp"  
            android:text="提示消息" />  

        <View  
            android:layout_width="match_parent"  
            android:layout_height="1px"  
            android:layout_marginTop="15dp"  
            android:background="#E4E4E4" />  

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

            <Button  
                android:id="@+id/no"  
                android:layout_width="0dp"  
                android:layout_height="match_parent"  
                android:layout_marginLeft="10dp"  
                android:layout_weight="1"  
                android:background="@null"  
                android:gravity="center"  
                android:singleLine="true"  
                android:text="No"  
                android:textColor="#7D7D7D"  
                android:textSize="16sp" />  

            <View  
                android:layout_width="1px"  
                android:layout_height="match_parent"  
                android:background="#E4E4E4" />  

            <Button  
                android:id="@+id/yes"  
                android:layout_width="0dp"  
                android:layout_height="match_parent"  
                android:layout_marginRight="10dp"  
                android:layout_weight="1"  
                android:background="@null"  
                android:gravity="center"  
                android:singleLine="true"  
                android:text="Yes"  
                android:textColor="#38ADFF"  
                android:textSize="16sp" />  
        </LinearLayout>  
    </LinearLayout>  
</RelativeLayout>

Dialog的自定义背景框如下:

<?xml version="1.0" encoding="utf-8"?>  
<shape xmlns:android="http://schemas.android.com/apk/res/android">  

    <solid android:color="#ffffff" />  
    <stroke  
        android:width="0.8dp"  
        android:color="#ffffff" />  
    <!-- 圆角 -->  
    <corners android:radius="6dp" />  

</shape>


第三步:继承Dialog实现自定义的Dialog,先上代码,供大家欣赏下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
package com.world.hello.selfdialog;  
  
import android.app.Dialog;  
import android.content.Context;  
import android.os.Bundle;  
import android.view.View;  
import android.widget.Button;  
import android.widget.TextView;  
  
/** 
 * 创建自定义的dialog,主要学习其实现原理 
 * Created by chengguo on 2016/3/22. 
 */  
public class SelfDialog extends Dialog {  
  
    private Button yes;//确定按钮  
    private Button no;//取消按钮  
    private TextView titleTv;//消息标题文本  
    private TextView messageTv;//消息提示文本  
    private String titleStr;//从外界设置的title文本  
    private String messageStr;//从外界设置的消息文本  
    //确定文本和取消文本的显示内容  
    private String yesStr, noStr;  
  
    private onNoOnclickListener noOnclickListener;//取消按钮被点击了的监听器  
    private onYesOnclickListener yesOnclickListener;//确定按钮被点击了的监听器  
  
    /** 
     * 设置取消按钮的显示内容和监听 
     * 
     * @param str 
     * @param onNoOnclickListener 
     */  
    public void setNoOnclickListener(String str, onNoOnclickListener onNoOnclickListener) {  
        if (str != null) {  
            noStr = str;  
        }  
        this.noOnclickListener = onNoOnclickListener;  
    }  
  
    /** 
     * 设置确定按钮的显示内容和监听 
     * 
     * @param str 
     * @param onYesOnclickListener 
     */  
    public void setYesOnclickListener(String str, onYesOnclickListener onYesOnclickListener) {  
        if (str != null) {  
            yesStr = str;  
        }  
        this.yesOnclickListener = onYesOnclickListener;  
    }  
  
    public SelfDialog(Context context) {  
        super(context, R.style.MyDialog);  
    }  
  
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.free_exercise_sure_dialog_layout);  
        //按空白处不能取消动画  
        setCanceledOnTouchOutside(false);  
  
        //初始化界面控件  
        initView();  
        //初始化界面数据  
        initData();  
        //初始化界面控件的事件  
        initEvent();  
          
    }  
  
    /** 
     * 初始化界面的确定和取消监听器 
     */  
    private void initEvent() {  
        //设置确定按钮被点击后,向外界提供监听  
        yes.setOnClickListener(new View.OnClickListener() {  
            @Override  
            public void onClick(View v) {  
                if (yesOnclickListener != null) {  
                    yesOnclickListener.onYesClick();  
                }  
            }  
        });  
        //设置取消按钮被点击后,向外界提供监听  
        no.setOnClickListener(new View.OnClickListener() {  
            @Override  
            public void onClick(View v) {  
                if (noOnclickListener != null) {  
                    noOnclickListener.onNoClick();  
                }  
            }  
        });  
    }  
  
    /** 
     * 初始化界面控件的显示数据 
     */  
    private void initData() {  
        //如果用户自定了title和message  
        if (titleStr != null) {  
            titleTv.setText(titleStr);  
        }  
        if (messageStr != null) {  
            messageTv.setText(messageStr);  
        }  
        //如果设置按钮的文字  
        if (yesStr != null) {  
            yes.setText(yesStr);  
        }  
        if (noStr != null) {  
            no.setText(noStr);  
        }  
    }  
  
    /** 
     * 初始化界面控件 
     */  
    private void initView() {  
        yes = (Button) findViewById(R.id.yes);  
        no = (Button) findViewById(R.id.no);  
        titleTv = (TextView) findViewById(R.id.title);  
        messageTv = (TextView) findViewById(R.id.message);  
    }  
  
    /** 
     * 从外界Activity为Dialog设置标题 
     * 
     * @param title 
     */  
    public void setTitle(String title) {  
        titleStr = title;  
    }  
  
    /** 
     * 从外界Activity为Dialog设置dialog的message 
     * 
     * @param message 
     */  
    public void setMessage(String message) {  
        messageStr = message;  
    }  
  
    /** 
     * 设置确定按钮和取消被点击的接口 
     */  
    public interface onYesOnclickListener {  
        public void onYesClick();  
    }  
  
    public interface onNoOnclickListener {  
        public void onNoClick();  
    }  
}

主actvitiy的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
package com.world.hello.selfdialog;  
  
import android.support.v7.app.AppCompatActivity;  
import android.os.Bundle;  
import android.view.View;  
import android.widget.Toast;  
  
public class MainActivity extends AppCompatActivity {  
  
    private SelfDialog selfDialog;  
  
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main);  
  
        findViewById(R.id.self_dialog).setOnClickListener(new View.OnClickListener() {  
            @Override  
            public void onClick(View v) {  
  
                selfDialog = new SelfDialog(MainActivity.this);  
                selfDialog.setTitle("提示");  
                selfDialog.setMessage("确定退出应用?");  
                selfDialog.setYesOnclickListener("确定", new SelfDialog.onYesOnclickListener() {  
                    @Override  
                    public void onYesClick() {  
                        Toast.makeText(MainActivity.this,"点击了--确定--按钮",Toast.LENGTH_LONG).show();  
                        selfDialog.dismiss();  
                    }  
                });  
                selfDialog.setNoOnclickListener("取消", new SelfDialog.onNoOnclickListener() {  
                    @Override  
                    public void onNoClick() {  
                        Toast.makeText(MainActivity.this,"点击了--取消--按钮",Toast.LENGTH_LONG).show();  
                        selfDialog.dismiss();  
                    }  
                });  
                selfDialog.show();  
            }  
        });  
    }  
}

好了,看了上面的例子,大家是不是觉得,以后都可以自定义自己的dialog了呢,这里在给大家讲讲具体原理:
就拿本例来说,我定义了一个title,一个message,一个确定按钮,一个取消按钮。

1、通过构造方法给dialog设置一个主题 R.style.MyDialog , 主要设置dialog的显示属性,一般都是 全透明无边框 ;

2、然后在dialog的onCreate()方法中,用setContentView( R.layout.SelfDialog) 为dialog设置XML文件,我们就可以在layout文件中创建自定义的Dialog风格。这里我就自定义了xml文件格式,实现了自定义的外观风格,不受系统的主题影响。

3、然后通过设置要为外界设置一些public 公开的方法,来向自定义的dialog传递值。这里的title 和 message,都是可以通过外界传值进来,进行设置的。如下面的public 方法就是供外界activity来设置title和message的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/** 
 * 从外界Activity为Dialog设置标题 
 * 
 * @param title 
 */  
public void setTitle(String title) {  
    titleStr = title;  
}  
      
/** 
 * 从外界Activity为Dialog设置dialog的message 
 * 
 * @param message 
 */  
public void setMessage(String message) {  
    messageStr = message;  
}

在activity通过实例化Dialog后就可以设置titile和message了。

1
2
3
selfDialog = new SelfDialog(MainActivity.this);  
selfDialog.setTitle("提示");  
selfDialog.setMessage("确定退出应用?");

4、最后,自定义的dialog中包含了一些按钮的时候,这个时候要想让按钮有点击事件,并且把这个点击事件能够传递给activity,让acitvity做一些事情,这里就需要设置监听接口,让button的点击事件能够让外界activity知道。如下面的代码。

1
2
3
4
5
6
7
8
9
10
/** 
    * 设置确定按钮和取消被点击的接口 
    */  
   public interface onYesOnclickListener {  
       public void onYesClick();  
   }  
  
   public interface onNoOnclickListener {  
       public void onNoClick();  
   }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
private onNoOnclickListener noOnclickListener;//取消按钮被点击了的监听器  
   private onYesOnclickListener yesOnclickListener;//确定按钮被点击了的监听器  
  
   /** 
    * 设置取消按钮的显示内容和监听 
    * 
    * @param str 
    * @param onNoOnclickListener 
    */  
   public void setNoOnclickListener(String str, onNoOnclickListener onNoOnclickListener) {  
       if (str != null) {  
           noStr = str;  
       }  
       this.noOnclickListener = onNoOnclickListener;  
   }  
  
   /** 
    * 设置确定按钮的显示内容和监听 
    * 
    * @param str 
    * @param onYesOnclickListener 
    */  
   public void setYesOnclickListener(String str, onYesOnclickListener onYesOnclickListener) {  
       if (str != null) {  
           yesStr = str;  
       }  
       this.yesOnclickListener = onYesOnclickListener;  
   }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//设置确定按钮被点击后,向外界提供监听  
       yes.setOnClickListener(new View.OnClickListener() {  
           @Override  
           public void onClick(View v) {  
               if (yesOnclickListener != null) {  
                   yesOnclickListener.onYesClick();  
               }  
           }  
       });  
       //设置取消按钮被点击后,向外界提供监听  
       no.setOnClickListener(new View.OnClickListener() {  
           @Override  
           public void onClick(View v) {  
               if (noOnclickListener != null) {  
                   noOnclickListener.onNoClick();  
               }  
           }  
       });

Activity就可以设置监听接口来实时获取button的点击事件如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
selfDialog.setYesOnclickListener("确定", new SelfDialog.onYesOnclickListener() {  
                   @Override  
                   public void onYesClick() {  
                       Toast.makeText(MainActivity.this,"点击了--确定--按钮",Toast.LENGTH_LONG).show();  
                       selfDialog.dismiss();  
                   }  
               });  
               selfDialog.setNoOnclickListener("取消", new SelfDialog.onNoOnclickListener() {  
                   @Override  
                   public void onNoClick() {  
                       Toast.makeText(MainActivity.this,"点击了--取消--按钮",Toast.LENGTH_LONG).show();  
                       selfDialog.dismiss();  
                   }  
               });

通过上面4步的详细讲解,就能知道自定义dialog的一般原理,基本就是 要为dialog设置一些基本的文字信息时,就直接用公开方法public 的方法,让外界直接设置;如果要让activity监听到button之类的点击事件就自定义接口,用监听接口的方式向activity传递点击事件。

最后附带一个简洁的方式,值得一看

简洁的Dialog

Material 风格的 Dialog 的使用

可以带动画以及底部弹出


设置Dialog布局的几种方式

如果丑的话要设置dialog的主题样式,继承Theme.Dialog
并在构造方法里面放入

1.关键在下面的两行,使用window.setContentView,替换整个对话框窗口的布局

Window window = dialog.getWindow();
window.setContentView(R.layout.alertdialog);

2.直接用dialog的setContentView

View layout = inflater.inflate(R.layout.dialog_share_qrcode, null);
dialog.addContentView(layout, new LayoutParams(
              android.view.ViewGroup.LayoutParams.WRAP_CONTENT
              , android.view.ViewGroup.LayoutParams.WRAP_CONTENT));
dialog.setContentView(layout);

修改普通对话框的位置、大小、透明度

主要是在普通的dialog.show() 下面加上如下代码

1
2
3
4
5
6
7
8
9
10
11
12
13
//放在show()之后,不然有些属性是没有效果的,比如height和width
Window dialogWindow = dialog.getWindow();
WindowManager m = getWindowManager();
Display d = m.getDefaultDisplay(); // 获取屏幕宽、高用
WindowManager.LayoutParams p = dialogWindow.getAttributes(); // 获取对话框当前的参数值
//设置高度和宽度
p.height = (int) (d.getHeight() * 0.4); // 高度设置为屏幕的0.6
p.width = (int) (d.getWidth() * 0.6); // 宽度设置为屏幕的0.65
//设置位置
p.gravity = Gravity.BOTTOM;
//设置透明度
p.alpha = 0.5f;
dialogWindow.setAttributes(p);

OR

1
2
3
4
5
Window dialogWindow = getWindow();
WindowManager.LayoutParams lp = dialogWindow.getAttributes();
DisplayMetrics d = context.getResources().getDisplayMetrics(); // 获取屏幕宽、高用
lp.width = (int) (d.widthPixels * 0.8); // 高度设置为屏幕的0.6
dialogWindow.setAttributes(lp);

原文链接:http://www.apkbus.com/blog-705730-62701.html

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消