Android对话框:Dialog

QuibblerQuibbler 2020-02-28 约 22 分钟 2231 次阅读

Android对话框:Dialog

对话框在Android开发中使用频率很高,各种弹框及数据选择输入,比如:时间选择器:DatePicker和TimePicker

默认的Dialog什么也没有,一般使用它的派生类AlertDialog,或者MaterialDialog。

Dialog dialog = new Dialog(this);
    dialog.show();

1、AlertDialog

AlertDialog比较常用,通过AlertDialog.Builder创建AlertDialog对话框并显示。AlertDialog.Builder常用方法:

setIcon():设置图标icon

setTitle():设置对话框标题

setMessage():设置对话框中间显示信息

setPositiveButton():确定

setNegativeButton():取消

setNeutralButton():中立

setCancelable(false):点击其它区域、返回键是否自动取消。(对于AlertDialog有效,DialogFragment无效)

1.1、基本弹框

取消-确认

AlertDialog.Builder builder = new AlertDialog.Builder(this);
        
        //设置Builder
        builder.setTitle("标题")
                .setMessage("Dialog内容")
                .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                    
                    }
                })
                .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                    
                    }
                });
        //显示
        builder.create().show();
        
        //或者
        //Dialog dialog = builder.create();
        //dialog.show();

添加Icon和setNeutralButton()

1.2、选择列表Dialog

两种方法设置Dialog的列表

//传入数组[]
    setItems(CharSequence[] items, final OnClickListener listener)
    //传入values/arrays.xml中定义的<string-array> id
    setItems(@ArrayRes int itemsId, final OnClickListener listener)

注意:设置setItems(),不要再设置setMessage(),否则只显示Message而不显示列表。

private String[] items = {"item 1", "item 2", "item 3", "item 4", "item 5", "item 6"};
    
    builder.setTitle("标题")
            .setIcon(R.drawable.layout_1)
            .setItems(items, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    //which就是选择列表的index
                }
            });

1.3、单选Dialog

setSingleChoiceItems方法设置单选,需要设置默认选中(一般第一个0)

setSingleChoiceItems(items, 0, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            //选择第which个
                        }
                    });

1.4、多选Dialog

定义多选列表和默认选中状态,因为多选所以传入的默认也需要是数组。

private String[] items = {"item 1", "item 2", "item 3", "item 4", "item 5", "item 6"};
    private boolean[] checkeds = {false, false, false, false, false, false};

设置setMultiChoiceItems()

setMultiChoiceItems(items, checkeds, new DialogInterface.OnMultiChoiceClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which, boolean isChecked) {
                        Log.d("QUIBBLER", "which = " + which + ",isChecked " + isChecked);
                    }
                });

1.5、输入Dialog

弹出对话框输入,自动弹出输入法,点击其它区域关闭对话框,收起输入法。setView()方法给Dialog添加一个EditText。曾经实现这个试了好多次,现在记录一下。

//创建输入EditText
        EditText editText = new EditText(this);
        editText.requestFocus();
       
        //Dialog配置
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle("输入对话框")
                .setView(editText)
                .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        Toast.makeText(mContext, editText.getText(), Toast.LENGTH_SHORT).show();
                    }
                })
                .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                    }
                })
                .create();
                
        //Dialog配置输入法,显示
        Dialog dialog = builder.create();
        dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
        dialog.show();

  是给Dialog 的Window设置setSoftInputMode()为WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE。如果在AndroidManifest给Activity设置android:windowSoftInputMode="stateAlwaysVisible",输入法将一直存在不能自动收起。

源码片段:

仔细捋一捋,AlertDialog继承自AppCompatDialog,AppCompatDialog继承自基类Dialog,在基类Dialog中有一个说明:

/**
     * Dialog类型的基类.
     * 
     * Note: Activities provide a facility to manage the creation, saving and
     * restoring of dialogs. See {@link Activity#onCreateDialog(int)},
     * {@link Activity#onPrepareDialog(int, Dialog)},
     * {@link Activity#showDialog(int)}, and {@link Activity#dismissDialog(int)}. If
     * these methods are used, {@link #getOwnerActivity()} will return the Activity
     * that managed this dialog.
     * 
     * Often you will want to have a Dialog display on top of the current
     * input method, because there is no reason for it to accept text.  You can
     * do this by setting the {@link WindowManager.LayoutParams#FLAG_ALT_FOCUSABLE_IM
     * WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM} window flag (assuming
     * your Dialog takes input focus, as it the default) with the following code:
     *
     * getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
     *         WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);</pre>
     */

Dialog.getWindow()源码及其说明如下:

/**
     * 检索Activity当前窗口。这可用于直接访问Activity/Screen中不可用的Window部分API。
     *
     * @return Window当前窗口,如果活动不可见,则为空。
     */
    public @Nullable Window getWindow() {
        return mWindow;
    }

2、ProgressDialog @deprecate

进度对话框

ProgressDialog progressDialog = new ProgressDialog(this);
        progressDialog.setIcon(R.mipmap.ic_launcher);
        progressDialog.setTitle("加载dialog");
        progressDialog.setMessage("加载中...");
        //精度条水平,默认是转圈圈
        progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        // 是否形成一个加载动画  true表示不明确加载进度形成转圈动画  false 表示明确加载进度
        progressDialog.setIndeterminate(true);
        //点击返回键或者dialog四周是否关闭dialog  true表示可以关闭 false表示不可关闭
        progressDialog.setCancelable(false);
        progressDialog.show();

3、自定义Dialog

定义好Layout布局,inflate成View,在setView()添加到Dialog即可

View view = LayoutInflater.from(mContext).inflate(R.layout.dialog_layout_my, null);
        //布局中的控件
        Button button = view.findViewById(R.id.button);
        button.setOnClickListener((v) -> {
            Toast.makeText(mContext, "点击Button", Toast.LENGTH_SHORT).show();
        });
        
        AlertDialog.Builder builder = new AlertDialog.Builder(this);        
        builder.setView(view)
                .show();

4、DialogFragment

默认的DialogFragment继承自Fragment,实现了Dialog相关接口。

public class DialogFragment extends Fragment implements DialogInterface.OnCancelListener, DialogInterface.OnDismissListener{
        ...
    }

不能使用默认的DialogFragment,因为什么都没有:

DialogFragment dialogFragment = new DialogFragment();
    dialogFragment.show(getSupportFragmentManager(), "DialogFragment");

自定义DialogFragment,继承DialogFragment,重写其中的public Dialog onCreateDialog(Bundle savedInstanceState)方法。注意不要和Fragment混淆,不要重写public View onCreateView(LayoutInflater inflater,ViewGroup container, Bundle savedInstanceState)方法。

public class MyDialogFragment extends DialogFragment {
    
        //在onCreate中拿到外部传入的参数
        public void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
        }
        
        //在onCreateDialog中构建一个alertDialog对象
        public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
            AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
            return builder.create();
        }
        
        //处理dismiss响应事件
        public void dismiss() {
            super.dismiss();
        }
    }

①在onCreate中拿到外部传入的参数

②在onCreateDialog中构建一个alertDialog对象

③通过DialogFragment的show()来显示对话框

和普通AlertDialog使用一样,相当于封装了AlertDialog,各司其职。

5、Dialog Style

Activity主题Theme有各种style,参考Android主题Theme探究。Dialog也有,默认弹出Dialog对话框,背景会变暗。

可以给Dialog也设置style样式,系统预定义了很多style。

<!--Dialog透明背景-->
    <style name="NoBackgroundDialog" parent="Theme.AppCompat.Light.Dialog.Alert">
        <!--        <item name="android:windowBackground">@android:color/transparent</item>-->
        <!--        <item name="android:windowIsTranslucent">false</item>-->
        <item name="android:backgroundDimEnabled">false</item>
    </style>

在创建AlertDialog.Builder 的时候style当做参数传入

//另一个重载的构造函数,传入Contex、style资源id
    AlertDialog.Builder builder = new AlertDialog.Builder(getContext(), R.style.NoBackgroundDialog);

6、第三方Dialog

在GitHub上看到很多开源的优秀项目,就有漂亮的Dialog可以使用和参考:

GitHub material-dialogs

GitHub FlycoDialog_Master

相关博客:

        Android 系统原生dialog使用

相关推荐

精选
ViewPager和PagerAdapter、FragmentPagerAdapter、FragmentStatePager
Android

ViewPager和PagerAdapter、FragmentPagerAdapter、FragmentStatePager

ViewPager1、ViewPagerandroidx.viewpager.widget.ViewPager,Android中使用非常广泛的控件,可以说是APP必备:首次打开引导页、页面Banner广告等。常用方法:setAdapter() 设置适配器setOffscreenPageLimit() 设置缓存的页面个数,默认是 1setCurrentItem() 跳转到特定的页面setOnPage

1.1k
获取Android内置WebView内核版本
Android

获取Android内置WebView内核版本

获取Android内置WebView内核版本竟然能遇到这样奇葩的事情,网页用的技术过于新颖,以至于只支持高版本Chromium内核的,低版本安卓系统中内置的内核版本较低,无法加载前端页面。1、设置查看在系统设置里 > 应用 > 应用管理 > 显示系统应用,查看WebView组件:2、页面查看通过WebView发起的网络请求,都会带上浏览器的UA,通常页面都可以通过UA判断浏览器的内核版本。这里有两

1.1w
Android 14适配总结
Android

Android 14适配总结

Android 14适配总结毕业工作至今已经适配了三个Android大版本,从Android 11到Android 12、再到Android 13。2023年,Google即将推出的Android 14,上半年已经开始第一批适配。现在,第四个Android版本已经适配完,总结记录一下。1、Android 14计划Google一般会在2月份对外发布预告,同时放出开发者预览版。“拉通”各大平台、厂商以

1.1w