Android 对话框相关总结

常用的对话框相关的有:AlertDialog,ProgressDialog,自定义的对话框(自定义的对话框的长宽设置需要注意),还有任意位置在其他应用上都可以弹出的对话框。其中任意位置在其他应用上都可以弹出的对话框见另一篇博文:点击跳转。该博文的demo放在gihub上:点击跳转。只有“将事件传递回对话框的宿主”的例子在module:”passEventToHost”里,其他都在dialog里。

1.纯粹的 AlertDialog以及设置位置

AlertDialog对话框是非常常用的对话框,一般又一个头部,中间的说明文字和下面的按钮组成。按钮的数量可以是:1、2或3。注意的是,下面按钮中,最前面到的那个按钮,在Android的不同版本中,位置是不同的。
下面给出代码:

 AlertDialog.Builder dialog = new AlertDialog.
                Builder(MainActivity.this);
        dialog.setTitle("对话框最上面的字");//对话框最上面的字
        dialog.setMessage("对话框中部的字");//对话框中部的字
        dialog.setCancelable(false);//如果是false,点击其他位置或者返回键无效,这个地方默认为true
//以下为对话框最下面的选择项
        dialog.setPositiveButton("右边", new DialogInterface.
                OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                Toast.makeText(MainActivity.this, "右边", Toast.LENGTH_SHORT).show();
            }

        });
        //需要第二个按钮才添加如下的setNegativeButton()
        dialog.setNegativeButton("左边", new DialogInterface.
                OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                Toast.makeText(MainActivity.this, "左边", Toast.LENGTH_SHORT).show();
            }

        });
        //需要第三个按钮时,才添加如下的setNeutralButton(),android老版本是在中间,比如4.0,在新版本是在前面,没有研究从哪个版本开始变的
        dialog.setNeutralButton("前面", new DialogInterface.
                OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                Toast.makeText(MainActivity.this, "前面", Toast.LENGTH_SHORT).show();
                dialog.dismiss();
            }
        });
        dialog.show();

在Android 8.0 模拟器上运行效果:

这里写图片描述

2. ProgressDialog和自定义对话框

虽然,ProgressDialog官方在Androidd 8.0中已经弃用它了:“This class was deprecated in API level 26.“,但是实际用Android 8.0模拟器运行并没有出现问题。而且官网没有给出效果相同的直接代替的类。只是建议用别的东西代替,如ProgressBar。
下面给出代码:

ProgressDialog progressDialog = new ProgressDialog
                (MainActivity.this);
        progressDialog.setTitle("对话框上部的字");
        progressDialog.setMessage("正在加载.....");
        progressDialog.setCancelable(true);//如果是false,点击其他位置或者返回键无效,默认为true
        progressDialog.show();
        //progressDialog.dismiss();//此句让progressDialog消失

在Android 8.0 模拟器上运行效果:
这里写图片描述
自定义对话框
下面给出一个简单的,避开弃用progressDialog问题的方法:自定义对话框。通过getInflater.inflate(R.layout.dialog_layout, null)获取View;通过builder.setView()给对话框设置view。这样设置的Dialog宽度始终会如右图下图所示,而高度是wrap_content且有一个最小值,不会比那个值小,在
布局文件dialog_layout.xml:

<?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="wrap_content"
    android:orientation="vertical">
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="20dp"
        android:layout_marginStart="20dp"
        android:layout_marginTop="15dp"
        android:orientation="horizontal">
        <ProgressBar

            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
        <TextView
            android:id="@+id/message"
            android:layout_marginLeft="20dp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:text="message"
            android:textSize="17sp"/>
    </LinearLayout>
</LinearLayout>

java代码如下,通过message.setText()改变下方显示文字, builder.setTitle()设置上方显示文字。

 AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
        LayoutInflater inflater = getLayoutInflater();
        View dialogView = inflater.inflate(R.layout.dialog_layout, null);
        builder.setView(dialogView).create();
        builder.setTitle("进度");
        TextView message = dialogView.findViewById(R.id.message);
        message.setText("进度:%10");
        builder.show();

下面对比一下,效果基本与ProgressDialog一致:

这里写图片描述

3. 自定义对话框(考虑wrap_content时的大小问题)

自定义对话框,就是自己写一个布局,让对话框加载布局,并且能监听这个布局里面的点击事件,并且对话框可以响应点击消失。需要注意的是,有时候自定义的根布局高和宽是wrap_content,这时定义的对话框长宽会失效,下面是考虑到这种问题的自定义对话框。但是比较麻烦,如果根布局大小可以写死,就不需要考虑这个问题
首先写一个对话框的布局:my_dialog.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:background="@color/colorAccent"
              android:orientation="vertical">

    <TextView
        android:layout_width="300dp"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="自定义对话框"
        android:textSize="20sp"/>

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_marginTop="20dp">

        <Button
            android:id="@+id/leftBt"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="左按钮"/>

        <Button
            android:id="@+id/rightBt"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="右按钮"/>
    </LinearLayout>

</LinearLayout>

设计对话框的style,目的是去控制对话框长宽,并且避免出现一些上部阴影,下面是添加在styles.xml中的代码,其中windowIsFloating让java代码部分控制大小生效,windowNoTitle避免出现一些上部阴影:

<style name="style_dialog" parent="android:style/Theme.Dialog">
        <item name="android:windowNoTitle">true</item>
        <item name="android:windowIsFloating">true</item>
    </style>

在java代码部分会用到上面的文件,注意一点:导入的AlertDialog语句是:import android.support.v7.app.AlertDialog;(不要导入错误成另一个)

 //获取自定义布局view实例
        View layout = LayoutInflater.from(this).inflate(R.layout.my_dialog, null);
        //在对话框里加载布局:setView()方法
        final AlertDialog.Builder dialog = new AlertDialog.
                Builder(MainActivity.this,R.style.style_dialog);
        dialog.setCancelable(false)//如果是false,点击其他位置或者返回键无效,这个地方默认为true
                .setView(layout);//这里加载布局
        final AlertDialog alert = dialog.create();

        //设置对话框的宽和高(注意,设置长宽还需要设置R.style.style_dialog,否则会出现很多问题),
        //并且如果需要设置布局大小,而不是wrap_content,那么需要在布局的子项里面设置大小,
        //直接在最外层设置是无效的
        Window window = alert.getWindow();
        window.getDecorView().setPadding(0, 0, 0, 0);//void setPadding (int left, int top,int right,int bottom)
        WindowManager.LayoutParams lp = window.getAttributes();
        lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
        lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
        window.setAttributes(lp);
        window.setGravity(Gravity.CENTER);//对话框出现的位置

        //按钮监听事件
        Button btLeft, btRight;
        btLeft = layout.findViewById(R.id.leftBt);
        btRight = layout.findViewById(R.id.rightBt);
        btLeft.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //这里写左按钮点击响应事件
                Toast.makeText(MainActivity.this, "左按钮", Toast.LENGTH_SHORT).show();
                alert.dismiss();//让对话框消失
            }
        });

        btRight.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //这里写右按钮点击响应事件
                Toast.makeText(MainActivity.this, "右按钮", Toast.LENGTH_SHORT).show();
                alert.dismiss();//让对话框消失
            }
        });
        alert.show();
    }

在拟器上运行效果:
这里写图片描述

4.单选列表对话框

添加builder.setItems()即可,setItems第一个参数是显示数据的数组,第二个是点击监听DialogInterface.OnClickListener对象。也可以使用 setAdapter() 指定一个列表。 这样一来,您就可以使用 ListAdapter 以动态数据(如来自数据库的数据)支持列表。

 String[] arr={"第一项","第二项","第三项"};
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle("单选列表对话框")
                .setItems(arr, new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        // which是点击列表位置
                        Toast.makeText(MainActivity.this, which+"", Toast.LENGTH_SHORT).show();
                    }
                });
         builder.create().show();
    }

效果是这样的:
这里写图片描述

5.多选列表对话框

需要定义一个List对象存储选定内容,在点击确定时读取。依靠setMultiChoiceItems()方法实现多选列表对话框。

List <String>mSelectedItems;//用于多选列表对话框选择项的暂时存储


String[] arr={"第一项","第二项","第三项"};
        mSelectedItems = new ArrayList();  //用来存放被选中的项
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        // Set the dialog title
        builder.setTitle("多选列表对话框")
                // Specify the list array, the items to be selected by default (null for none),
                // and the listener through which to receive callbacks when items are selected
                .setMultiChoiceItems(arr, null,
                        new DialogInterface.OnMultiChoiceClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which,
                                                boolean isChecked) {
                                if (isChecked) {
                                    // 如果选择一项,那么在选定的项中添加此项
                                    mSelectedItems.add(which+"");
                                } else if (mSelectedItems.contains(which)) {
                                    // 如果取消选择,那么在选定的项中移除此项
                                    mSelectedItems.remove(Integer.valueOf(which));
                                }
                            }
                        })
                // Set the action buttons
                .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int id) {
                        //确定
                        String result="";
                        for(String str:mSelectedItems){
                            result+=str;
                        }
                        //这里输出被选中项
                        Toast.makeText(MainActivity.this, result, Toast.LENGTH_SHORT).show();
                    }
                })
                .setNegativeButton("cancel", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int id) {
                        //取消
                    }
                });

         builder.create().show();

效果如下:
这里写图片描述

6.全屏的对话框

1.状态栏消失,屏幕全部占满的对话框

建议使用Dialog而不是AlertDialog,因为AlertDialog自带的一些属性使全屏变得比Dialog麻烦一些。Dialog与AlertDialog代码上的区别,主要是它没有Builder,而是直接在Dialog上对对话框属性进行设置。而要让Dialog全屏是非常简单的,只需要在实例化Dialog对象时像这样传递参数即可。注意,这样的话,屏幕上方状态栏也会消失,对话框占据整个屏幕(除虚按键)。

Dialog dialog = new Dialog(this,android.R.style.
Theme_Light_NoTitleBar_Fullscreen);

完整的一个自定义布局的全屏对话框代码:

public showDialog(Activity activity){
Dialog dialog = new Dialog(activity,
android.R.style.Theme_Light_NoTitleBar_Fullscreen);//第二参数为关键代码
        View view = LayoutInflater.from(activity).
        inflate(R.layout.diag_list, null, false);//diag_list是对话框的布局文件
        dialog.setContentView(view);
        //这里区别于AlertDialog,Builder的setView(View)

        dialog.show();
}

下面在提供一种状态栏不消失的全屏对话框的方法:

2.让状态栏显示的全屏对话框

需要设置对话框长宽都是match_parent,因为默认是wrap_content

dialog.getWindow().setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager
                .LayoutParams.MATCH_PARENT);

需要设置Dialog的背景,因为它默认背景会距离屏幕上下左右各8dp

dialog.getWindow().setBackgroundDrawable(null);
//注意,以上写法会使dialog背景透明,可以在对话框布局文件中设置布局背景色。
//或像下面一样,设背景色为白色
//dialog.getWindow().setBackgroundDrawable(new 
//ColorDrawable(getResources().getColor(android.R.color.white)));

以上两步可以使Dialog全屏(不包含状态栏),下面一个完整例子:


 public void showDialog(Activity activity) {
        Dialog dialog = new Dialog(activity);//一个参数
        View view = LayoutInflater.from(activity).inflate(R.layout.diag_list, null, false);
        dialog.setContentView(view);

        dialog.getWindow().setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager
                .LayoutParams.MATCH_PARENT);
        dialog.getWindow().setBackgroundDrawable(new ColorDrawable(activity.getResources().getColor(android.R.color.white)));
        dialog.show();

    }
  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值