Android AlertDialog和PopupWindow使用和区别

一、前言:

在实际的开发中,我们经常会用到弹框,以此来显示一个警告或提醒或者提供一系列选项让用户选择。前段时间在开发时,要用到弹框,突然意识到好像两个都可以完成需求,当时我在想,那它们到底有什么区别呢?于是查了相关资料后,整理如下:

1. AlertDialog的基本属性和用法

AlertDialog是Dialog的子类,所以它包含了Dialog类的很多属性和方法,由于AlertDialog的构造方法全部是Protected的,所以不能直接通过new一个AlertDialog来创建出一个AlertDialog。

要创建一个AlertDialog,就要用到AlertDialog.Builder中的create()方法。

使用AlertDialog.Builder创建对话框需要了解以下几个方法:

setTitle :为对话框设置标题 setIcon :为对话框设置图标 setMessage:为对话框设置内容 setView : 给对话框设置自定义样式 setItems :设置对话框要显示的一个list,一般用于显示几个命令时 setMultiChoiceItems :用来设置对话框显示一系列的复选框 setNeutralButton :普通按钮

setPositiveButton :给对话框添加"Yes"按钮 setNegativeButton :对话框添加"No"按钮 create : 创建对话框 show :显示对话框

 AlertDialog alertDialog = new AlertDialog.Builder(this). 
             setTitle("对话框的标题"). 
             setMessage("对话框的内容"). 
             setIcon(R.drawable.ic_launcher). 
             create(); 
             alertDialog.show(); 

setItems(CharSequence[] items, final OnClickListener listener)方法来实现类似ListView的AlertDialog

第一个参数是要显示的数据的数组,第二个参数是点击某个item的触发事件

final String[] array = new String[] { "悬疑", "都市", "爱情", "动作" ,"惊悚"}; 
 
              Dialog alertDialog = new AlertDialog.Builder(this).
                setTitle("你喜欢什么样的电影?").
                setIcon(R.drawable.ic_launcher)
                .setItems(array, new DialogInterface.OnClickListener() {
             
                 @Override
                 public void onClick(DialogInterface dialog, int which) {
                  Toast.makeText(getApplicationContext(), array[which], Toast.LENGTH_SHORT).show();
                 }
                }).
                setNegativeButton("取消", new DialogInterface.OnClickListener() {
 
                 @Override
                 public void onClick(DialogInterface dialog, int which) {
                  // TODO Auto-generated method stub
                 }
                }).
                create();
              alertDialog.show();
图片.png

setSingleChoiceItems(CharSequence[] items, int checkedItem, final OnClickListener listener)方法来实现类似RadioButton的AlertDialog

第一个参数是要显示的数据的数组,第二个参数是初始值(初始被选中的item),第三个参数是点击某个item的触发事件

final int selectedFruitIndex = 0;
            final String[] arrayFruit = new String[] { "苹果", "橘子", "草莓", "香蕉" };
 
              Dialog alertDialog = new AlertDialog.Builder(this).
                setTitle("你喜欢吃哪种水果?").
                setIcon(R.drawable.ic_launcher)
                .setSingleChoiceItems(arrayFruit, 0, new DialogInterface.OnClickListener() {
             
                 @Override
                 public void onClick(DialogInterface dialog, int which) {
                  //selectedFruitIndex = which;
                 }
                }).
                setPositiveButton("确认", new DialogInterface.OnClickListener() {
 
                 @Override
                 public void onClick(DialogInterface dialog, int which) {
                  Toast.makeText(getApplicationContext(), arrayFruit[selectedFruitIndex], Toast.LENGTH_SHORT).show();
                 }
                }).
                setNegativeButton("取消", new DialogInterface.OnClickListener() {
 
                 @Override
                 public void onClick(DialogInterface dialog, int which) {
                  // TODO Auto-generated method stub
                 }
                }).
                create();
              alertDialog.show();

setMultiChoiceItems(CharSequence[] items, boolean[] checkedItems, final OnMultiChoiceClickListener listener)方法来实现类似CheckBox的AlertDialog
第一个参数是要显示的数据的数组,第二个参数是选中状态的数组,第三个参数是点击某个item的触发事件

final String[] arrayFruit = new String[] { "苹果", "橘子", "草莓", "香蕉" }; 
        final boolean[] arrayFruitSelected = new boolean[] {true, true, false, false}; 
 
        Dialog alertDialog = new AlertDialog.Builder(this). 
                setTitle("你喜欢吃哪种水果?"). 
                setIcon(R.drawable.ic_launcher) 
                .setMultiChoiceItems(arrayFruit, arrayFruitSelected, new DialogInterface.OnMultiChoiceClickListener() { 
                     
                    @Override 
                    public void onClick(DialogInterface dialog, int which, boolean isChecked) { 
                        arrayFruitSelected[which] = isChecked; 
                    } 
                }). 
                setPositiveButton("确认", new DialogInterface.OnClickListener() { 
 
                    @Override 
                    public void onClick(DialogInterface dialog, int which) { 
                        StringBuilder stringBuilder = new StringBuilder(); 
                        for (int i = 0; i < arrayFruitSelected.length; i++) { 
                            if (arrayFruitSelected[i] == true) 
                            { 
                                stringBuilder.append(arrayFruit[i] + "、"); 
                            } 
                        } 
                        Toast.makeText(Dialog_AlertDialogDemoActivity.this, stringBuilder.toString(), Toast.LENGTH_SHORT).show(); 
                    } 
                }). 
                setNegativeButton("取消", new DialogInterface.OnClickListener() { 
 
                    @Override 
                    public void onClick(DialogInterface dialog, int which) { 
                        // TODO Auto-generated method stub  
                    } 
                }). 
                create(); 
        alertDialog.show(); 
    } 
} 
图片.png

实际中,我们也经常会自定义View,来满足我们的开发需求
比如说我们要实现一个Login画面,有用户名和密码,这时我们就要用到自定义View的AlertDialog

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:orientation="vertical" > 
 
    <LinearLayout 
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content" 
        android:gravity="center" > 
 
        <TextView 
            android:layout_width="0dip" 
            android:layout_height="wrap_content" 
            android:layout_weight="1" 
            android:text="@string/user" /> 
 
        <EditText 
            android:layout_width="0dip" 
            android:layout_height="wrap_content" 
            android:layout_weight="1" /> 
    </LinearLayout> 
 
    <LinearLayout 
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content" 
        android:gravity="center" > 
 
        <TextView 
            android:layout_width="0dip" 
            android:layout_height="wrap_content" 
            android:layout_weight="1" 
            android:text="@string/passward" /> 
 
        <EditText 
            android:layout_width="0dip" 
            android:layout_height="wrap_content" 
            android:layout_weight="1" /> 
    </LinearLayout> 
 
</LinearLayout> 

然后在Activity中去加载我们的布局

// 取得自定义View  
        LayoutInflater layoutInflater = LayoutInflater.from(this); 
        View myLoginView = layoutInflater.inflate(R.layout.login, null); 
         
        Dialog alertDialog = new AlertDialog.Builder(this). 
                setTitle("用户登录"). 
                setIcon(R.drawable.ic_launcher). 
                setView(myLoginView). 
                setPositiveButton("登录", new DialogInterface.OnClickListener() { 
 
                    @Override 
                    public void onClick(DialogInterface dialog, int which) { 
                        // TODO Auto-generated method stub  
                    } 
                }). 
                setNegativeButton("取消", new DialogInterface.OnClickListener() { 
 
                    @Override 
                    public void onClick(DialogInterface dialog, int which) { 
                        // TODO Auto-generated method stub  
                    } 
                }). 
                create(); 
        alertDialog.show(); 
    } 

2. PopupWindow的属性和方法及使用

它可以使用任意布局的View作为其内容,这个弹出框是悬浮在当前activity之上的。

PopupWindow的位置按照有无偏移分,可以分为偏移和无偏移两种;按照参照物的不同,可以分为相对于某个控件(Anchor锚)和相对于父控件。具体如下

showAsDropDown(View anchor):相对某个控件的位置(正左下方),无偏移
showAsDropDown(View anchor, int xoff, int yoff):相对某个控件的位置,有偏移
showAtLocation(View parent, int gravity, int x, int y):相对于父控件的位置(例如正中央Gravity.CENTER,下方Gravity.BOTTOM等),可以设置偏移或无偏移

View popView = LayoutInflater.from(this).inflate(
                    R.layout.pop_style, null);
            pop = new PopupWindow(popView, 400, 350);
            pop.setBackgroundDrawable(new BitmapDrawable());//这些要在show之前设置,否则无法作用
            pop.setOutsideTouchable(true);
            Button popButton = (Button) popView.findViewById(R.id.button1);
            popButton.setOnClickListener(new OnClickListener() {
                
                @Override
                public void onClick(View v) {
                    // TODO 自动生成的方法存根
                    Log.e("pop----->", "bt");
                }
            });
            pop.showAtLocation(bt2, Gravity.CENTER, 0, 0);

其中的bt2是点击弹出框相对于它的显示位置

 int[] location = new int[2];
                view.getLocationOnScreen(location);
                pop.showAtLocation(view, Gravity.NO_GRAVITY, (ScreenUtils.getScreenWidth() - pop.getWidth()) / 2, location[1] - pop.getHeight() + 10);

修改popwindown显示的位置
注意:有时候比如点击button后天弹出对话框,当点击外部时,弹框消失。这时候可能会遇到一个问题:假如点击的外部区域是button,这个时候就会出现button先消失,后又出现的问题。大多数情况下,我们这时候还是希望点击button时弹框消失就好了,再次点击button时就出现。为此,可以这样做:
1)在你点击弹出popowinddow的view上添加点击事件view.setOnClick(false)
2)在popwind初始化后设置

popupwindow.setOnDismissListener(new PopupWindow.OnDismissListener() {
@Override
public void onDismiss() {
handler.postDelayed(new Runnable() {
@Override
public void run() {
view.setClickable(true);
}
}, 100);
}
});

3. AlertDialog和PopupWindow的区别

(1)Popupwindow在显示之前一定要设置宽高,Dialog无此限制。

(2)Popupwindow默认不会响应物理键盘的back,除非显示设置了popup.setFocusable(true);而在点击back的时候,Dialog会消失。

(3)Popupwindow不会给页面其他的部分添加蒙层,而Dialog会。

(4)Popupwindow没有标题,Dialog默认有标题,可以通过dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);取消标题

(5)二者显示的时候都要设置Gravity。如果不设置,Dialog默认是Gravity.CENTER。

(6)二者都有默认的背景,都可以通过setBackgroundDrawable(new ColorDrawable(android.R.color.transparent));去掉。

其中最本质的差别就是:AlertDialog是非阻塞式对话框:AlertDialog弹出时,后台还可以做事情;而PopupWindow是阻塞式对话框:PopupWindow弹出时,程序会等待,在PopupWindow退出前,程序一直等待,只有当我们调用了dismiss方法的后,PopupWindow退出,程序才会向下执行。这两种区别的表现是:AlertDialog弹出时,背景是黑色的,但是当我们点击背景,AlertDialog会消失,证明程序不仅响应AlertDialog的操作,还响应其他操作,其他程序没有被阻塞,这说明了AlertDialog是非阻塞式对话框;PopupWindow弹出时,背景没有什么变化,但是当我们点击背景的时候,程序没有响应,只允许我们操作PopupWindow,其他操作被阻塞。我们在写程序的过程中可以根据自己的需要选择使用Popupwindow或者是Dialog。


原文链接:https://blog.csdn.net/android_cmos/article/details/51223776

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,142评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,298评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,068评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,081评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,099评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,071评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,990评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,832评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,274评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,488评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,649评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,378评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,979评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,625评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,643评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,545评论 2 352

推荐阅读更多精彩内容