Android技术知识Android开发经验谈Android开发

android.support.v7.app.AlertDial

2020-01-08  本文已影响0人  blingbling_5a3f

一:基本使用

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监听返回键的点击。

上一篇下一篇

猜你喜欢

热点阅读