android.support.v7.app.AlertDial

作者: blingbling_5a3f | 来源:发表于2020-01-08 11:04 被阅读0次

    一:基本使用

    1、显示消息

    AlertDialog.Builder builder = new AlertDialog.Builder(this);
                builder.setTitle("Title")
                        .setMessage("message")
                        .setIcon(R.drawable.ic_info_black_24dp)
                        .setPositiveButton(android.R.string.ok, null)
                        .setNegativeButton(android.R.string.cancel, null)
                        .show();
    
    效果: dialog.png

    2、显示列表

    CharSequence[] charSequence = new CharSequence[]{"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N"};
            AlertDialog.Builder builder = new AlertDialog.Builder(this);
            builder.setTitle("Title")
                    .setItems(charSequence, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            //TODO
                        }
                    })
                    .setPositiveButton(android.R.string.ok, null)
                    .show();
    
    list_dialog.png

    此时如果数据有更新怎么办,我们就需要找到ListAlertDialog里面的ListView的Adapter,然后通知更新就可以了。
    代码可以像下面这么写:

    final CharSequence[] charSequence = new CharSequence[]{"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N"};
                AlertDialog.Builder builder = new AlertDialog.Builder(this);
                final AlertDialog dialog = builder.setTitle("Title")
                        .setItems(charSequence, new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                //TODO
                            }
                        })
                        .setPositiveButton(android.R.string.ok, null)
                        .show();
                AsyncTask.execute(new Runnable() {
                    @Override
                    public void run() {
                        SystemClock.sleep(1500);
                        charSequence[1] = "BBBBB";
                        charSequence[2] = "ZZZZZ";
                        if (dialog.isShowing()) {
                            ListView listView = dialog.getListView();
                            final BaseAdapter adapter = (BaseAdapter) listView.getAdapter();
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    adapter.notifyDataSetChanged();
                                }
                            });
                        }
                    }
                });
    

    这里起一个线程模拟耗时任务,listView.getAdapter()获得的对象为ListAdapter,但是ListAdapter没有notifyDataSetChanged()方法,查看源码发现他使用的就是CheckedItemAdapter,而CheckedItemAdapter的父类就继承自BaseAdapter,这里就强转成BaseAdapter就可以了。
    3、显示单选和多选列表
    显示单选列表,类似RadioGroup。

    CharSequence[] charSequence = new CharSequence[]{"A", "B", "C", "D", "E", "F", "G"};
            AlertDialog.Builder builder = new AlertDialog.Builder(this);
            builder.setTitle("Title")
                    .setSingleChoiceItems(charSequence, 1,new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            //TODO
                        }
                    })
                    .setPositiveButton(android.R.string.ok, null)
                    .show();
    

    显示多选列表。

    CharSequence[] charSequence = new CharSequence[]{"A", "B", "C", "D", "E", "F", "G"};
            boolean[] booleans = new boolean[]{false, true, false, false, false, true, false};
            AlertDialog.Builder builder = new AlertDialog.Builder(this);
            builder.setTitle("Title")
                    .setMultiChoiceItems(charSequence, booleans, new DialogInterface.OnMultiChoiceClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which, boolean isChecked) {
    
                        }
                    })
                    .setPositiveButton(android.R.string.ok, null)
                    .show();
    

    4、Cursor+列表

    String[] projection = new String[]{
                        MediaStore.MediaColumns.TITLE,
                        MediaStore.MediaColumns._ID
                };
                Cursor cursor = getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                        projection, null, null, null);
                new AlertDialog.Builder(this)
                        .setTitle("Image Name")
                        .setMultiChoiceItems(cursor,
                                MediaStore.MediaColumns._ID,
                                MediaStore.MediaColumns.TITLE,
                                new DialogInterface.OnMultiChoiceClickListener() {
                                    @Override
                                    public void onClick(DialogInterface dialog, int which, boolean isChecked) {
    
                                    }
                                })
                        .setPositiveButton(android.R.string.ok, null)
                        .show();
    
    multi_chioce.png
    5、自定义
    1:setView设置内容区域,不包括Title和底部按钮
    View mContentView = LayoutInflater.from(this).inflate(R.layout.alert_dialog_editext, null);
                new AlertDialog.Builder(this)
                        .setTitle("Input Name")
                        .setView(mContentView)
                        .setPositiveButton(android.R.string.ok, null)
                        .show();
    
    custom_view.png

    2:setCustomTitle自定义标题,替换原有的Title和Icon所在的布局,所以此时setTitle和setIcon两个方法的设置是无效的

    View mTitleView = LayoutInflater.from(this).inflate(R.layout.title_view, null);
                new AlertDialog.Builder(this)
                        .setMessage("This is Message")
                        .setCustomTitle(mTitleView)
                        .setPositiveButton(android.R.string.ok, null)
                        .show();
    
    custom_view.png

    二:主题样式

    1、构造器
    Builder有两个构造器:

    public Builder(Context context) {
                this(context, resolveDialogTheme(context, ResourceId.ID_NULL));
            }
    
    public Builder(Context context, int themeResId) {
                P = new AlertController.AlertParams(new ContextThemeWrapper(
                        context, resolveDialogTheme(context, themeResId)));
            }
    

    只有一个参数的会生成一个默认的样式给AlertDialog,这个样式会跟随Activity的主题;
    第二个构造器需要自己传入一个样式。
    2、修改样式
    1:Style控制样式

    <style name="DialogTheme" parent="ThemeOverlay.AppCompat.Dialog.Alert">
            <item name="android:textColorPrimary">#FF00FF</item>
            <item name="colorAccent">#00FFFF</item>
            <item name="android:textSize">20sp</item>
        </style>
    

    textColorPrimary:设置Title和Message的颜色;
    colorAccent:设置Button文字的颜色;
    android:textSize:控制Button文字的大小。

    new AlertDialog.Builder(this, R.style.DialogTheme)
                    .setMessage("This is Message")
                    .setTitle("Title")
                    .setPositiveButton(android.R.string.ok, null)
                    .show();
    
    style.png

    2:Message和Button的颜色动态修改

    AlertDialog alertDialog = new AlertDialog.Builder(this)
                        .setMessage("This is Message")
                        .setTitle("Title")
                        .setPositiveButton(android.R.string.ok, null)
                        .setNegativeButton(android.R.string.cancel, null)
                        .show();
                TextView msg = alertDialog.findViewById(android.R.id.message);
                msg.setTextColor(0x80000000);
                Button pBtn = alertDialog.getButton(DialogInterface.BUTTON_POSITIVE);
                if (pBtn != null) {
                    pBtn.setTextColor(getResources().getColor(R.color.colorAccent));
                }
                Button nBtn = alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE);
                if (nBtn != null) {
                    nBtn.setTextColor(getResources().getColor(R.color.colorAccent));
                }
    

    android.R.id.message:Message所在TextView的ID;
    getButton(DialogInterface.BUTTON_POSITIVE):PositiveButton;
    getButton(DialogInterface.BUTTON_NEGATIVE):NegativeButton。
    其中Title所在View的ID是android:id="@+id/alertTitle",但是通过findViewById是找不到的。
    3、Material Design规范颜色和字号

    materil_design.png
    Title text:颜色87%透明度的黑,字体android:fontFamily="sans-serif-medium",文字大小20sp;
    Message text:颜色54%透明度的黑,字体android:fontFamily="sans-serif",文字大小16sp;
    Button:颜色跟随主题色,字体android:fontFamily="sans-serif-medium",文字大小14sp;

    三:问题Bug

    1、华为android6.0/7.0/8.0等系统的手机开启单手模式,Dialog展示的位置有问题,左右距离不等(貌似华为在android9.0修复了此问题)。

    问题手机截图: 单手模式.png
    正常手机截图: 单手模式.png

    2、条件:①、小米android9.0以上系统
    ②、开启全屏模式
    ③、Dialog里面的内容的列表可以滚动
    结果:Dialog展示时会跳动一下。


    跳动.gif
    正常.gif
    3、条件:①、Activity的主题里面包含<item name="android:windowTranslucentStatus">true</item>
    ②、Dialog里面的内容列表可以滚动
    结果:Dialog展示时会跳动一下(不是所有手机都存在这个问题,而且如果使用的是Android API下的AlertDialog是不会出问题的)。
    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
            <item name="colorPrimary">@color/colorPrimary</item>
            <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
            <item name="colorAccent">@color/colorAccent</item>
            <item name="android:windowTranslucentStatus">true</item>
        </style>
    
    String[] strings = new String[50];
            for (int i = 0; i < strings.length; i++) {
                strings[i] = i + "";
            }
            AlertDialog.Builder builder = new AlertDialog.Builder(this);
            builder.setTitle("Title")
                    .setSingleChoiceItems(strings, 0, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
    
                        }
                    })
                    .setPositiveButton(android.R.string.ok, null)
                    .show();
    
    跳动.gif

    四:进阶

    1、dialog.dismiss();可以在子线程调用而不会崩溃。
    源码:

    @Override
        public void dismiss() {
            if (Looper.myLooper() == mHandler.getLooper()) {
                dismissDialog();
            } else {
                mHandler.post(mDismissAction);
            }
        }
    

    2、在dialog的cancel()方法里面会调用dismiss()方法,所以当调用cancel()方法时onCancel和onDismiss都接收到回调,而且顺序是先回调给onCancel然后回调给onDismiss。
    源码:

    @Override
        public void cancel() {
            if (!mCanceled && mCancelMessage != null) {
                mCanceled = true;
                // Obtain a new message so this dialog can be re-used
                Message.obtain(mCancelMessage).sendToTarget();
            }
            dismiss();
        }
    

    3、可以通过给Dialog设置setOnKeyListener监听返回键的点击。

    相关文章

      网友评论

        本文标题:android.support.v7.app.AlertDial

        本文链接:https://www.haomeiwen.com/subject/ofrfpqtx.html