zoukankan      html  css  js  c++  java
  • 最全AltertDialog 你只需要这一篇就够了

    简单介绍一下自己,大三学生党一枚!主攻Android开发,对于Web和后端均有了解。

    个人语录:取乎其上,得乎其中,取乎其中,得乎其下,以顶级态度写好一篇的博客。


    AlertDialog在实际开发过程中经常用到,并且根据场景不同,设计的提示也大相径庭,前几天我遇到一个需求:弹出提示的同时播放铃声,本来以为很简单,过程跌宕起伏让人抓狂!在这本该陪女盆友的一天,我却在写博客(说的我好像有女盆友一样!)

    在这里插入图片描述

    一.AlertDialog的基础知识

    1.1 AlertDialog的构造函数

    AlertDialog大体上来说有两个重载构造函数

    //只需要传入上下文context即可,最后会调用具有默认布局的第二个构造函数。
     AlertDialog.Builder alertDialog1 = new AlertDialog.Builder(Context context);
    //传入上下文,同时传入自定义的布局
     AlertDialog.Builder alertDialog2 = new AlertDialog.Builder(context, R.layout.xxx);

    1.2 辅助类函数介绍

    builder.setMessage(CharSequence char);
      //设置提示信息,传入字符串即可
      builder.setIcon(Drawable drawable|int id);
      //设置提示的图标,可以传入资源id,也可以传入Drawable对象
      builder.setTitle(CharSequence char|int id);
      //设置提示的标题,传入字符串或者id
      builder.setView();
      //设置对话框内容为自定义view,仅设置内容区
      builder.setContentView();
      //设置对话框为自定义view,设置全部
      builder.setInverseBackgroundForced();
      //已经被弃用,用来更改默认的背景颜色
      builder.setCustomTitle();
      //自定义Title,可设置背景颜色
      builder.setCancelable(true);
      //如果设置为true则是可取消,点击屏幕其他区域,提示框自动消失,若设置false则不可
      builder.setAdapter()
      //设置对话框内容为自定义列表框
      builder.setItems(int id,Listener listener)
      //设置对话框为简单列表项,传入一个资源数组id和一个列表监听器
      builder.setMultiChoiceItems();
      //该方法也是简单列表,传入一个数组和一个boolean类型数组和一个监听器

    函数真的好多,为了写博客一一验证,改了很多次描述,现在应该比较贴切了
    在这里插入图片描述

    1.3 AlertDialog的一些问题

    AlertDialog.Builder(context).create()的返回值为AlertDialog,但是AlertDialog并不能直接实例化,需要借助AlertDialog.Builder来创建。我们简单的浏览几个重要的源码片段来学习他们的不同。

    1.3.1 dialog.show()和builder.show()的区别

    public AlertDialog show() {
    //在内部创建dialog,最后调用dialog.show(),也就是说builder.show()是调用dialog.show()方法的
                final AlertDialog dialog = create();
                dialog.show();
                return dialog;
            }

    1.3.2 builder的一系列设置方法是怎么添加到dialog中的?

    public static class Builder {
        //在builder内部有一个 成员变量P,看名字就知道是“关于显示(dialog)的一些列参数”
        //从builder.create()中可以得到验证
            @UnsupportedAppUsage
            private final AlertController.AlertParams P;
            }
    public AlertDialog create() {
               
                final AlertDialog dialog = new AlertDialog(P.mContext, 0, false);
                P.apply(dialog.mAlert);
                //设置dialog的一些列细节信息,如icon,message,都是在Builder中进行设置的,
                //最后调用builder.create()方法,把所有信息传递给dialog
                dialog.setCancelable(P.mCancelable);
                if (P.mCancelable) {
                    dialog.setCanceledOnTouchOutside(true);
                }
                dialog.setOnCancelListener(P.mOnCancelListener);
                dialog.setOnDismissListener(P.mOnDismissListener);
                if (P.mOnKeyListener != null) {
                    dialog.setOnKeyListener(P.mOnKeyListener);
                }
                return dialog;
            }

    1.3.3 AlertDialog的默认布局是如何的?

    先用一张图来展示

    在这里插入图片描述


    之前提到setView()方法可以设置内容区,内容区是在message下面,Buttton上面的一块区域。而setContentView()则可以设置整块区域。可以通过设置style修改默认的AlertDialog的背景。setCustomTitle()其实就是修改setTitle这块的内容,可以传入TextView,并设置TextView的颜色,这样就可以改变默认背景的颜色。

    1.3.4 unable to add window的异常

    在这里插入图片描述
    解决方案:查看传入的Context是否正确。


    在这里插入图片描述

    二.AlertDialog的实战情景

    2.1 消息提示型

    简单描述:消息提示类没有复杂的操作,可能只有一个“我知道了”的按钮,是最简单的一种提示。但是默认的提示太丑了,先贴出默认提示,最后再自定义一个消息提示。

    AlertDialog.Builder builder =createMessageDialog(v.getContext());
                    builder.setIcon(R.drawable.photo);
                    builder.setMessage("明天上午10点,xxx约您在中南海见面");
                    builder.setTitle("重要通知");
                    builder.setPositiveButton("我知道了", new AlertDialog.OnClickListener(){
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            Toast.makeText(getApplicationContext(), "您已接受邀请,请准时赴约", Toast.LENGTH_SHORT).show();
                            //这里可以做一些其他操作
                        }
                    });
                    builder.show();

    效果图如下:
    在这里插入图片描述


    这个提示的代码很简单,下面贴一个自定义的消息提示,时间匆忙,没有做的很好看。

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
        android:orientation="vertical"
        android:background="#888888"
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <TextView
            android:gravity="center_horizontal"
            android:text="重要通知"
            android:textColor="#EEEEEE"
            android:layout_marginTop="8dp"
            android:textSize="22sp"
            android:layout_width="match_parent"
            android:layout_height="40dp">
        </TextView>
        <TextView
            android:layout_marginTop="10dp"
            android:gravity="center_horizontal"
            android:textSize="18sp"
            android:textColor="#CCCCCC"
            android:text="明天上午10点,xxx约您在见面"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
        </TextView>
        <Button
            android:gravity="center_horizontal"
            android:text="我知道了"
            android:textSize="16sp"
            android:layout_marginTop="30dp"
            android:background="@null"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
        </Button>
    </LinearLayout>
    AlertDialog.Builder builder =createMessageDialog(v.getContext());
                      builder.setView(R.layout.layout_alert);
                      builder.show();
                      //三行代码加布局搞定一切

    效果图展示:
    在这里插入图片描述
    如果需要添加Button的点击,可以通过android:onClick="xxx";并在代码中声明该方法即可。

    2.2 逻辑操作型

    逻辑操作类型,其实就是底部多了很多按钮,可以进行不同的操作,代码如下:

    AlertDialog.Builder builder =createMessageDialog(v.getContext());
                    View view = getLayoutInflater().inflate(R.layout.layout_alert, null);
                    builder.setView(view);
                    TextView textView = new TextView(v.getContext());
                    textView.setText("Android");
                    builder.setCancelable(true);
                    textView.setBackgroundColor(getResources().getColor(R.color.colorAccent));
                    builder.setCustomTitle(textView);
                    builder.setNegativeButton("取消", new AlertDialog.OnClickListener(){
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            Toast.makeText(getApplicationContext(), "您点击了取消", Toast.LENGTH_SHORT).show();
                        }
                    });
                    builder.setPositiveButton("确定", new AlertDialog.OnClickListener(){
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            Toast.makeText(getApplicationContext(), "您点击了确定", Toast.LENGTH_SHORT).show();
                        }
                    });
                    builder.setNeutralButton("中立的", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            Toast.makeText(getApplicationContext(), "您点击了中立", Toast.LENGTH_SHORT).show();
                        }
                    });
                    builder.setView(R.layout.layout_alert);
                    builder.show();

    效果图如下:
    在这里插入图片描述
    这里同样也可以自定义,只需要和之前那样,声明按钮的点击方法即可,就不再演示。

    2.3 列表选择型

    builder.setTitle("选择你最喜爱的城市");
                    builder.setMultiChoiceItems(province, new boolean[]{true, true, true},
                            new OnMultiChoiceClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which, boolean isChecked) {
                                    switch (which) {
                                        case 0:
                                            Toast.makeText(getApplicationContext(), "您选择了A", Toast.LENGTH_SHORT).show();
                                            break;
                                        case 1:
                                            Toast.makeText(getApplicationContext(), "您选择了B", Toast.LENGTH_SHORT).show();
                                            break;
                                        case 2:
                                            Toast.makeText(getApplicationContext(), "您选择了c", Toast.LENGTH_SHORT).show();
                                            break;
                                    }
                                }
                            });
                    builder.show();



    效果展示:


    在这里插入图片描述


    这里做一个仿网易云播放列表的案例

    builder2.setIcon(R.drawable.play);
                    TextView textView1 = new TextView(getApplicationContext());
                    textView1.setText("播放列表");
                    textView1.setTextSize(22);
                    builder2.setCustomTitle(textView1);
                    //顶部已经设置好
                    String[] songs = new String[]{"演员","聊表心意","花儿与少年","天后","狐狸","七里香","一路向北"};
                    String[] singers = new String[]{"薛之谦","薛之谦","薛之谦","陈势安","薛之谦","周杰伦","周杰伦"};
                    int[] photo = new int[]{R.drawable.xue,R.drawable.xue,R.drawable.xue,R.drawable.chen,R.drawable.xue,R.drawable.zhou,R.drawable.zhou};
                    View view1 = getLayoutInflater().inflate(R.layout.layout_alert, null);
                    RecyclerView recyclerView = view1.findViewById(R.id.recyclerview);
                    SongAdapter adapter = new SongAdapter(photo, songs, singers, getApplicationContext());
                    recyclerView.setAdapter(adapter);
                    recyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
                    builder2.setView(view1);
                    builder2.show();

    layout_alert

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
        android:orientation="vertical"
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/recyclerview"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
        </androidx.recyclerview.widget.RecyclerView>
    </LinearLayout>

    song_item

    <?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="80dp">
        <ImageView
            android:layout_margin="6dp"
            android:id="@+id/singer_photo"
            android:src="@drawable/xue"
            android:layout_width="80dp"
            android:layout_height="80dp"
            android:scaleType="fitXY">
        </ImageView>
        <LinearLayout
            android:id="@+id/song"
            android:layout_toRightOf="@id/singer_photo"
            android:orientation="vertical"
            android:layout_marginLeft="16dp"
            android:layout_width="wrap_content"
            android:layout_height="match_parent">
            <TextView
                android:id="@+id/songs"
                android:textSize="20sp"
                android:text="认真的雪"
                android:textColor="#000000"
                android:layout_marginTop="5dp"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">
            </TextView>
            <TextView
                android:id="@+id/singer"
                android:textSize="16sp"
                android:text="薛之谦"
                android:textColor="#555555"
                android:layout_marginTop="10dp"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">
            </TextView>
        </LinearLayout>
    
    
            <ImageView
                android:layout_alignParentRight="true"
                android:layout_centerVertical="true"
                android:layout_width="32dp"
                android:layout_height="32dp"
                android:scaleType="center"
                android:layout_marginRight="42dp"
                android:src="@drawable/start"></ImageView>
    
            <ImageView
                android:layout_alignParentRight="true"
                android:layout_centerVertical="true"
                android:layout_width="32dp"
                android:layout_height="32dp"
                android:scaleType="center"
                android:src="@drawable/more"></ImageView>
    </RelativeLayout>

    SongAdapter

    class SongAdapter extends RecyclerView.Adapter<ViewHolder>{
            private int[] photos;
            private String[] songs;
            private String[] singers;
            private Context context;
    
            public SongAdapter(int[] photos,String[] songs,String[] singers,Context context){
                this.photos=photos;
                this.songs=songs;
                this.singers=singers;
                this.context=context;
            }
    
    
            @NonNull
            @Override
            public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
                View view = LayoutInflater.from(context).inflate(R.layout.song_item,null);
                ViewHolder viewHolder = new ViewHolder(view);
                return viewHolder;
            }
    
            @Override
            public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
                 holder.imageView.setImageDrawable(getResources().getDrawable(photos[position]));
                 holder.songs.setText(songs[position]);
                 holder.singer.setText(singers[position]);
            }
    
    
            @Override
            public int getItemCount() {
                return photos.length;
            }
    
        }
    
        class ViewHolder extends RecyclerView.ViewHolder{
            ImageView imageView;
            TextView songs;
            TextView singer;
            public ViewHolder(@NonNull View itemView) {
                super(itemView);
                imageView = itemView.findViewById(R.id.singer_photo);
                songs = itemView.findViewById(R.id.songs);
                singer = itemView.findViewById(R.id.singer);
            }
        }

    效果图,差的不是一点半点哈哈哈哈哈

    在这里插入图片描述



    在这里插入图片描述


    2.4 自定义提示

    自定义提示其实上面已经用到过了,比如自定义的消息提示,自定义的网易云播放列表等,最终要的是思想,我们可以把自定义的布局当成Activity的布局去设计他,大部分情况下,都是可用的。

    提一个小案例:淘宝软件上,我们在点击查看已发货时,会弹出一个提示,类似于ViewPager+Fragment结合设计的功能更加复杂的AlertDialog
    在这里插入图片描述


    自定义提示的步骤如下:

    第一步:根据需求,自定义Layout布局
    第二步:根据逻辑,将Layout布局转换成view,初始化布局中需要改变的控件。

    View view1 = getLayoutInflater().inflate(R.layout.layout_alert, null);
                    RecyclerView recyclerView = view1.findViewById(R.id.recyclerview);

    第三步:添加事件逻辑,如点击,选择,改变UI等。


    2.5 封装提示类

    提示在应用中比较常用,建议把AlertDialog封装起来,使用更方便。下面封装一个自定义类型的AlertDialog

    public static AlertDialog.Builder 
        createMessageDialog(Context context,String title,String message, int photoId, int layoutId,boolean setview){
           AlertDialog.Builder builder = new AlertDialog.Builder(context);
           if(title!=null){
               builder.setTitle(title);
           }
           if(message!=null){
               builder.setMessage(message);
           }
           try{
                Drawable drawable = context.getResources().getDrawable(photoId);
                builder.setIcon(drawable);
           }catch (NullPointerException e){
                //do something
           }
            View view = LayoutInflater.from(context).inflate(layoutId, null);
           if(setview){
               //设置内容布局
               builder.setView(view);
           }else{
               //设置setContentView,要找builder.show()以后调用
           }
           return builder;
        }

    三.AlertDialog高级进阶

    3.1 设置AlertDialog入场出场动画

    先上效果图:
    在这里插入图片描述
    这个效果非常简单,就是通过设置动画进行实现的,请看下列实现代码

    //this关键字很重要,使用getApplicationContext会出错。
    AlertDialog.Builder builder =new AlertDialog.Builder(this);
                    builder.setIcon(R.drawable.photo);
                    builder.setMessage("明天上午10点,XXX约您在见面");
                    builder.setTitle("重要通知");
                    builder.setPositiveButton("我知道了", new AlertDialog.OnClickListener(){
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            Toast.makeText(getApplicationContext(), "您点击了确定", Toast.LENGTH_SHORT).show();
                        }
                    });
    
                    Dialog dialog = builder.create();
                    //在这里指定动画
                    dialog.getWindow().getAttributes().windowAnimations = R.style.dialogWindowAnim;
                    dialog.show();

    style.xml

    <style name="dialogWindowAnim" parent="android:Animation" mce_bogus="1">  
                    <item name="android:windowEnterAnimation">@anim/dialog_enter_anim</item>  
                    <item name="android:windowExitAnimation">@anim/dialog_exit_anim</item>  
        </style>

    两个简单的动画

    <?xml version="1.0" encoding="utf-8"?>
    <translate xmlns:android="http://schemas.android.com/apk/res/android"
            android:duration="500"
            android:fromXDelta="0"
            android:fromYDelta="0"
            android:toXDelta="0"
            android:toYDelta="1000" >
    </translate>
    <?xml version="1.0" encoding="utf-8"?>
    <translate xmlns:android="http://schemas.android.com/apk/res/android"
         android:duration="100"
         android:fromXDelta="0"
         android:fromYDelta="1000"
         android:toXDelta="0"
         android:toYDelta="0" >
    </translate>

    3.2 待补充

    四 .小结

    这篇博客耗时两天,总结了AlertDialog的大部分问题,时间有限,如有错误,请各位前辈指出,感谢各位看官。

    相关阅读:

    抖音运营

    成版人抖音

    抖音和哔哩哔哩有什么不同

  • 相关阅读:
    14.4.6 Configuring Thread Concurrency for InnoDB 配置Thread 并发
    14.4.5 Configuring InnoDB Change Buffering 配置InnoDB Change Buffering
    14.4.4 Configuring the Memory Allocator for InnoDB InnoDB 配置内存分配器
    timeout connect 10000 # default 10 second time out if a backend is not found
    haproxy 服务端超时时间 timeout server 17000 --后台程序17秒没有响应,返回超时
    Openstack组件部署 — Nova_安装和配置Controller Node
    Openstack组件部署 — Nova_安装和配置Controller Node
    输出和模型使用 2
    输出和模型使用 1
    Openstack组件部署 — Nova overview
  • 原文地址:https://www.cnblogs.com/hzcya1995/p/13309122.html
Copyright © 2011-2022 走看看