天天看点

Android_UI:DialogDialog :Builder模式创建Dialog:构造方法创建DialogFragment仿ios透明加载框系统级的Dialog注意

  • Dialog :Builder模式创建
    • Dialog常用的方法
    • setButton(…)
    • dialog消失的2种方法的区别!
    • Dialog效果图
    • AlertDialog:基本对话框
      • 效果图:
      • 相关的类
      • Builder的相关的方法
      • 代码:
      • 注意:
    • Dialog添加列表
    • AlertDialog:单选对话框
      • 效果图:
      • 相关的方法
      • 代码:
    • AlertDialog多选对话框
      • 效果图:
      • Builder的相关的方法
      • 点开dialog显示上一次退出时选中的按钮
      • 代码:
    • ProgressDialog:进度条对话框
      • 效果图:
      • 相关的方法
      • 设置进度条:
      • 代码:
    • 自定义Dialog
      • 效果图:
      • 相关
      • 代码:
    • 自定义Dialog:加 动画 + 设置宽高 + style
      • 效果图:
      • 相关
      • 设置宽 + 高
      • 添加动画
      • 代码:
  • Dialog:构造方法创建
    • ProgressDialog
    • DatePickerDialog
      • DatePickerDialog 不重写setButton()
        • 效果图
        • 代码
      • DatePickerDialog 重写setButton()
        • 效果图
        • 代码
    • TimePickerDialog
      • TimePickDialog:不重写setButton()
        • 效果图
        • 代码
      • TimePickDialog:重写setButton()
        • 效果图
        • 代码
    • 其它
  • DialogFragment
    • 创建dialog
    • 显示dialog
    • Demo
      • DialogFragment01
      • DialogFragment02
      • DialogFragment03
    • 使用DialogFragment怎么把value传给Activity?
  • 仿ios透明加载框
      • 效果图
      • 工具类
      • WindowManager.LayoutParams.FLAG_DIM_BEHIND
    • 二:采用了帧动画
      • 需要复制的内容
      • progress_drawable_list.xml 帧动画
      • ProgressDialogUtil2
  • 系统级的Dialog
    • 效果图
    • 权限+Type
    • 其它
  • 注意
    • dialog的Context不能使用getApplicationContext()
    • dialog.setCanceledOnTouchOutside(false)无效

参考:

Android API 指南:Dialog: https://developer.android.google.cn/guide/topics/ui/dialogs.html#ShowingADialog

Dialog :Builder模式创建

dialog的监听可以为null,按“确定”、“取消”仍然有效。

对话框分类 含义
Dialog 基类:非抽象
AlertDialog 提醒对话框
ProgressDialog 进度条对话框

Dialog背景色是黑色,这是因为style的原因:

这些对话框都继承自Dialog,API18:

见图:

Android_UI:DialogDialog :Builder模式创建Dialog:构造方法创建DialogFragment仿ios透明加载框系统级的Dialog注意

Dialog常用的方法

方法 含义
setContentView(View or resId) 填充布局
findViewById(resId) 找到布局中的控件,可以用dialog调用
setTitle(character char) 设置比提提
setIcon(resId) 设置图标
show() 显示
dismiss() 消失:从屏幕中移除
hide() 隐藏
isShow() dialog是否正在显示
getWindow() 得到当前dialog所在的activity的窗体
类Dialog是没有方法:setMessage(charseQuence char),但是子类AlertDialog + ProgressDialog有此方法。

setButton(…)

dialog.setButton(…)

dialog.setButton(DialogInterface.BUTTON_POSITIVE, "确定", new DialogInterface.OnClickListener() {
    @Override
    public void onClick(DialogInterface dialog, int which) {

    }
});
dialog.setButton(DialogInterface.BUTTON_NEGATIVE, "取消", dialog);
dialog.setButton(DialogInterface.BUTTON_NEUTRAL, "中立", dialog);
           
dialog.setButton("自定义Button:确定", dialog);
dialog.setButton2("自定义Button:取消", dialog);
           

builder.setPositiveButton(…)

builder.setTitle("选择时间")
 .setCancelable(false)
 .setIcon(android.R.drawable.ic_dialog_info)
 .setSingleChoiceItems(times, , new DialogInterface.OnClickListener() {
     @Override
     public void onClick(DialogInterface dialog, int which) {
         //
     }
 })
 .setPositiveButton("确定", new DialogInterface.OnClickListener() {
     @Override
     public void onClick(DialogInterface dialog, int which) {
         //
     }
 })

 .setNegativeButton("选择日期", new DialogInterface.OnClickListener() {
     @Override
     public void onClick(DialogInterface dialog, int which) {
         //
     }
 });
           

dialog消失的2种方法的区别!

setCancelable(boolean flag) :点击back键dialog是否消失
setCanceledOnTouchOutside(boolean cancel) : 点击dialog意外的区域dialog是否消失
           

见developer

Android_UI:DialogDialog :Builder模式创建Dialog:构造方法创建DialogFragment仿ios透明加载框系统级的Dialog注意

Dialog效果图

Android_UI:DialogDialog :Builder模式创建Dialog:构造方法创建DialogFragment仿ios透明加载框系统级的Dialog注意

AlertDialog:基本对话框

继承自Dialog,默认显示在屏幕中间,左右两边距离屏幕有间隔。

效果图:

Android_UI:DialogDialog :Builder模式创建Dialog:构造方法创建DialogFragment仿ios透明加载框系统级的Dialog注意

相关的类

含义
AlertDialog 提醒对话框
AlertDialog.Builder 对话框构造器

Builder的相关的方法

方法 含义
setPositiviButton(String ,DialogInterface.onClickListener(..)) 设置确定按钮
setNogetiveButton(String ,DialogInterface.onClickListener(..)) 设置取消按钮
setMessage(charseQuence char) 设置dialog内容
crete() 创建dialog对象

代码:

// 普通对话框
private void initAlertDialog() {
    Builder builder = new AlertDialog.Builder(context);
    builder.setTitle("更新提示");
    builder.setMessage("这是知乎最新版本,请更新!");
    builder.setIcon(R.drawable.ic_launcher);
    builder.setPositiveButton("取消", new DialogInterface.OnClickListener() {

        @Override
        public void onClick(DialogInterface dialog, int which) {
            ToastUtil.showShortToast(context, "确定" + which);
            // dialog.dismiss();//可以不调用dismiss(),dialog会自动消失
        }
    });
    builder.setNegativeButton("确定", new DialogInterface.OnClickListener() {

        @Override
        public void onClick(DialogInterface dialog, int which) {
            ToastUtil.showShortToast(context, "取消" + which);
            // dialog.dismiss();可以不调用dismiss(),dialog会自动消失
        }
    });
    AlertDialog dialog = builder.create();
    dialog.show();
}
           

注意:

AlertDialog的方法setNegativeButton(CharSequence text, OnClickListener listener) + setPositiveButton(CharSequence text, OnClickListener listener) + setPositiveButton(CharSequence text, OnClickListener listener) 会自动调用dialog的dismiss(),除此之外均如果需要让dialog消失,都必须调用dismiss().

设置单选对话框和多选对话框时,不能调用方法setMessage(charseQuence char),否则选择列表不会显示。

Dialog添加列表

可通过 AlertDialog API 提供三种列表:

  • 传统单选列表
  • 永久性单选列表(单选按钮)
  • 永久性多选列表(复选框)

checkedItem:默认选中的position。-1表示默认不选中任何一个。

.setSingleChoiceItems(provinces, -, new DialogInterface.OnClickListener() {
    @Override
    public void onClick(DialogInterface dialog, int which) {
       //which表示选中的item在items中的角标
    }
})
           
AlertDialog dialog = new AlertDialog.Builder(this)
    .setTitle("Title")
    .setIcon(R.mipmap.ic_launcher_round)
    .setSingleChoiceItems(provinces, -, new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            Log.d(TAG, "singleChoice,which=" + which);
        }
    })
    .setPositiveButton("确定", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            Log.d(TAG, "Positive,which=" + which);
        }
    })
    .setNegativeButton("取消", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            Log.d(TAG, "Negative,which=" + which);
        }
    })
    .create();
dialog.show();
           

AlertDialog:单选对话框

效果图:

Android_UI:DialogDialog :Builder模式创建Dialog:构造方法创建DialogFragment仿ios透明加载框系统级的Dialog注意

相关的方法

含义
setSingleChoiceItems(CharSequence[] items, int checkedItem, OnClickListener listener) 设置单选对话框
items 所有选项
checkedItem 默认选中哪一个,-1:默认都没选

代码:

private void initSingleChoiceDialog() {
    AlertDialog.Builder builder = new AlertDialog.Builder(context);
    builder.setTitle("标题");
    // builder.setMessage("message--message");//设置message就没有了单选列表
    builder.setIcon(R.drawable.ic_launcher);
    final String[] items = new String[] { "item1", "item2", "item3", "item4", "item5" };
    final boolean[] checkedItem = new boolean[]{false,false,false,false,false};
    builder.setSingleChoiceItems(items, -,
            new DialogInterface.OnClickListener() {

                @Override
                public void onClick(DialogInterface dialog, int which) {
                    checkedItem[which] = true;
                    ToastUtil.showShortToast(context, items[which]);
                    dialog.dismiss();// 点击单选按钮,dialog不会自动消失
                }
            });
    AlertDialog dialog = builder.create();
    dialog.show();
}
           

AlertDialog多选对话框

效果图:

Android_UI:DialogDialog :Builder模式创建Dialog:构造方法创建DialogFragment仿ios透明加载框系统级的Dialog注意

Builder的相关的方法

方法 含义
setMultiChoiceItems(CharSequence[] items, boolean[] checkedItems, OnMultiChoiceClickListener listener) 多选方法
参数 含义
items 多选列表的内容
checkedItems ,默认选中的内容

点开dialog显示上一次退出时选中的按钮

把checkedItems 的创建放在类中,作为类变量。

代码:

private void initMultiChoiceDialog() {
    AlertDialog.Builder builder = new AlertDialog.Builder(context);
    builder.setTitle("Title");
    // builder.setMessage("message--message");//设置message就没有了单选列表
    builder.setIcon(R.drawable.ic_launcher);
    items = new String[] { "item1", "item2", "item3", "item4", "item5" };
    final boolean[] checkedItems = new boolean[] { false, false, false,
            false, false };
    builder.setMultiChoiceItems(items, checkedItems,
            new DialogInterface.OnMultiChoiceClickListener() {

                @Override
                public void onClick(DialogInterface dialog, int which,
                        boolean isChecked) {
                    ToastUtil.showShortToast(context, items[which]);
                }
            });
    builder.setPositiveButton("取消", new DialogInterface.OnClickListener() {

        @Override
        public void onClick(DialogInterface dialog, int which) {
            ToastUtil.showShortToast(context, "取消");
            // dialog.dismiss();//可以不调用dismiss(),dialog会自动消失
        }
    });
    builder.setNegativeButton("确定", new DialogInterface.OnClickListener() {

        @Override
        public void onClick(DialogInterface dialog, int which) {
            StringBuffer sb = new StringBuffer();
            for (int i = ; i < checkedItems.length; i++) {
                if (checkedItems[i]) {
                    sb.append(items[i]);
                }
            }
            ToastUtil.showShortToast(context, "确定" + sb.toString());
            // dialog.dismiss();可以不调用dismiss(),dialog会自动消失
        }
    });
    AlertDialog dialog = builder.create();
    dialog.show();
}
           

如何获选中的数据?

除了遍历

boolean[] checkedItems

外,还可以创建一个List,选中时添加到List,取消后从List中清除

ArrayList<String> selectedList = new ArrayList<>();
           
selectedList.clear();

builder.setMultiChoiceItems(provinces, null, new DialogInterface.OnMultiChoiceClickListener() {
    @Override
    public void onClick(DialogInterface dialog, int which, boolean isChecked) {
        Log.d(TAG, "MultiChoice,which=" + which + ",isChecked=" + isChecked);
        if (isChecked) {
            selectedList.add(provinces[which]);
        } else if (selectedList.contains(provinces[which])) {
            selectedList.remove(provinces[which]);
        }
    }
})
           

ProgressDialog:进度条对话框

分为线性和圆形,没有Builder.

效果图:

Android_UI:DialogDialog :Builder模式创建Dialog:构造方法创建DialogFragment仿ios透明加载框系统级的Dialog注意
Android_UI:DialogDialog :Builder模式创建Dialog:构造方法创建DialogFragment仿ios透明加载框系统级的Dialog注意

相关的方法

含义
setProgressStyle(int style) 设置进度条样式
setMax(int max) 进度最大值
setProgress(int value) 设置当前进度

设置进度条:

dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);// 水平线进度条
dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);// 圆形进度条
           

代码:

private void initProgressDialog() {
    final ProgressDialog dialog = new ProgressDialog(context);
    dialog.setTitle("Title");//设置标题
    dialog.setMessage("message----message");//设置dialog内容
    dialog.setIcon(R.drawable.ic_launcher);//设置图标,与为Title左侧
    dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);// 水平线进度条
    // dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);//圆形进度条
    dialog.setMax();//最大值
    new Thread() {
        public void run() {
            for (int i = ; i <= ; i++) {
                SystemClock.sleep();
                dialog.setProgress(i);//每隔50毫秒设置当前进度
            }
            dialog.dismiss();// for执行完成后dialog默认不消失
        };
    }.start();
    dialog.show();
}
           

自定义Dialog

需要自己设置布局

效果图:

Android_UI:DialogDialog :Builder模式创建Dialog:构造方法创建DialogFragment仿ios透明加载框系统级的Dialog注意

相关

含义
window 窗体
方法 含义
setGravity(int gravity) 设置窗体位置
含义
Dialog
方法 含义
requestWindowFeature(int featureId) 窗体的title是否显示

代码:

private void initCustomDialog() {
    final Dialog dialog = new Dialog(context);
    dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);// 去掉dialog的title,放在设置布局前
    dialog.setContentView(R.layout.custom_dialog);

    dialog.getWindow().setGravity(Gravity.BOTTOM);

    Button btn_ok = (Button) dialog.findViewById(R.id.btn_ok);
    Button btn_cancle = (Button) dialog.findViewById(R.id.btn_cancle);

    btn_ok.setOnClickListener(new Button.OnClickListener() {

        @Override
        public void onClick(View v) {
            dialog.dismiss();
        }
    });
    btn_cancle.setOnClickListener(new Button.OnClickListener() {

        @Override
        public void onClick(View v) {
            dialog.dismiss();
        }
    });
    dialog.show();
}
           

自定义Dialog:加 动画 + 设置宽高 + style

效果图:

Android_UI:DialogDialog :Builder模式创建Dialog:构造方法创建DialogFragment仿ios透明加载框系统级的Dialog注意

相关

类:Window

方法 含义
方法 含义
setGravity(int gravity) 设置窗体位置
getAttributes() 获取当前窗体的参数
setAttributes(LayoutParams a) 设置窗体宽高
setWindowAnimations(int resId) 给窗体添加动画

类:Dialog

方法 含义
requestWindowFeature(int featureId) 窗体的title是否显示
setCanceledOnTouchOutside(boolean cancel) 点击dialog意外的区域,dialog是否消失

设置宽 + 高

//设置 宽 + 高
LayoutParams params = window.getAttributes();//获取当前窗体的参数
view.measure(, );
params.width = getResources().getDisplayMetrics().widthPixels;
params.height = view.getMeasuredHeight();//不设置高的话,dialog会充满屏幕,下方是白色,即使在布局中设置了高的具体值

window.setAttributes(params);
           

添加动画

DialogAnimationStyle:

<style name="DialogAnimationStyle" parent="android:Animation">
    <item name="android:windowEnterAnimation">@anim/dialog_enter</item>
    <item name="android:windowExitAnimation">@anim/dialog_exit</item>
</style>
           

dialog_enter.xml:

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

dialog_exit.xml

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

MyStyle.xml

<style name="MyStyle">
    <item name="android:windowNoTitle">true</item>
    <item name="android:backgroundDimEnabled">true</item>
</style>
           

代码:

private void initCustomDialog2() {
    final Dialog dialog = new Dialog(context , R.style.MyStyle);//去掉dialog的title,dialog区域外是灰色
//      dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);// 去掉dialog的title,放在设置布局前
    View view = View.inflate(context, R.layout.custom_dialog2, null);
    dialog.setContentView(view);
    dialog.setCanceledOnTouchOutside(true);//点击dialog意外的区域,dialog是否消失

    Window window = dialog.getWindow();//创建当前窗体
    window.setGravity(Gravity.BOTTOM);//当前床底位于底部

    //添加动画
    window.setWindowAnimations(R.style.DialogAnimationStyle);

    //设置 宽 + 高
    LayoutParams params = window.getAttributes();//获取当前窗体的参数
    view.measure(, );
    params.width = getResources().getDisplayMetrics().widthPixels;
    params.height = view.getMeasuredHeight();//不设置高的话,dialog会充满屏幕,下方是白色,即使在布局中设置了高的具体值

    window.setAttributes(params);

    Button btn_camera  = (Button) dialog.findViewById(R.id.btn_camera);
    Button btn_gallery  = (Button) dialog.findViewById(R.id.btn_gallery);
    Button btn6_cancle  = (Button) dialog.findViewById(R.id.btn6_cancle);

    btn_camera.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            ToastUtil.showShortToast(context, "btn_camera");
            dialog.dismiss();
        }
    });

    btn_gallery.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            ToastUtil.showShortToast(context, "btn_gallery");
            dialog.dismiss();
        }
    });

    btn6_cancle.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            ToastUtil.showShortToast(context, "btn6_cancle");
            dialog.dismiss();
        }
    });

    dialog.show();//显示dialog
}
           
源码:https://github.com/s1168805219/DialogDemo

再魅族手机中,虚拟按键会遮挡bottomDialog的下方,解决的方法是在设置window的高度是加上虚拟键的高度

public class VirtualHeightUtil {


    public static int getDpi(Activity activity) {
        Display display = activity.getWindowManager().getDefaultDisplay();
        DisplayMetrics dm = new DisplayMetrics();
        int height = ;
        @SuppressWarnings("rawtypes")
        Class c;
        try {
            c = Class.forName("android.view.Display");
            @SuppressWarnings("unchecked")
            Method method = c.getMethod("getRealMetrics", DisplayMetrics.class);
            method.invoke(display, dm);
            height = dm.heightPixels;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return height;
    }

    public static int[] getScreenWH(Context poCotext) {
        WindowManager wm = (WindowManager) poCotext.getSystemService(Context.WINDOW_SERVICE);
        if (wm == null) {
            return new int[]{, };
        } else {
            int width = wm.getDefaultDisplay().getWidth();
            int height = wm.getDefaultDisplay().getHeight();
            return new int[]{width, height};
        }
    }

    /**
     * 获取魅族手机的虚拟键高度
     * @param poCotext
     * @return
     */
    public static int getVirtualBtnHeight(Context poCotext) {
        int location[] = getScreenWH(poCotext);
        int realHeiht = getDpi((Activity) poCotext);
        int virtualHeight = realHeiht - location[];
        return virtualHeight;
    }

}
           

Dialog:构造方法创建

我们知道设置模式有构建者模式,也就是Builder模式,上面我们创建Dialog就是这么做的。其实采用构造方法也可以创建Dialog。

比如:

Dialog

ProgressDialog

DatePickerDialog

TimePickerDialog

都可以采用构造方法创建dialog,但是

AlertDialog

不可以。

其中:

DatePickerDialog

TimePickerDialog

也可以使用fragment来显示,见:Android_UI:Date & Time组件(下)

Android_UI:DialogDialog :Builder模式创建Dialog:构造方法创建DialogFragment仿ios透明加载框系统级的Dialog注意
Android_UI:DialogDialog :Builder模式创建Dialog:构造方法创建DialogFragment仿ios透明加载框系统级的Dialog注意
Android_UI:DialogDialog :Builder模式创建Dialog:构造方法创建DialogFragment仿ios透明加载框系统级的Dialog注意
Android_UI:DialogDialog :Builder模式创建Dialog:构造方法创建DialogFragment仿ios透明加载框系统级的Dialog注意
Android_UI:DialogDialog :Builder模式创建Dialog:构造方法创建DialogFragment仿ios透明加载框系统级的Dialog注意
Android_UI:DialogDialog :Builder模式创建Dialog:构造方法创建DialogFragment仿ios透明加载框系统级的Dialog注意

ProgressDialog

见上面

DatePickerDialog

**注意:**DatePickerDialog和TimePickerDialog 都有方法

setButton(...)

,当我们重写该方法后,那么监听

OnDateSetListener

OnTimeSetListener

就无效了,不会走这2个监听,下面在重写

setButton()

中会有说明

DatePickerDialog 不重写setButton()

效果图

Android_UI:DialogDialog :Builder模式创建Dialog:构造方法创建DialogFragment仿ios透明加载框系统级的Dialog注意

代码

Calendar calendar = Calendar.getInstance();
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);
DatePickerDialog datePickerDialog = new DatePickerDialog(context, onDateSetListener, year, month, dayOfMonth);

datePickerDialog.setCanceledOnTouchOutside(false);
datePickerDialog.setCancelable(false);
datePickerDialog.show();
           

DatePickerDialog 重写setButton()

重写

setButton()

, 通过

getDatePicker()

获取到

DatePicker

对象,进而获取到year+month+day,所以不需要

OnDateSetListener

注意:

TimePickDialog

确没有相似的方法

getTimePicker()

,所以需要

OnTimeSetListener

重写

setButton(...)

后,监听

OnDateSetListener

OnTimeSetListener

就无效了。所以如果重写刚方法,那么不需要写listener,直接传null。

dialog默认有2个Button,如果我们只重写了一个

setButton(...)

,那么另一个“确定”/“取消”也会显示出来,那么怎么不让它显示出来呢,还是不设置为 “”,会显示默认文字
dialog.setButton2("", new DialogInterface.OnClickListener() {
     @Override
      public void onClick(DialogInterface dialog, int which) {
         //不写
      }
});
           

但是不能是:

dialog.setButton2("",null);
           

效果图

Android_UI:DialogDialog :Builder模式创建Dialog:构造方法创建DialogFragment仿ios透明加载框系统级的Dialog注意

代码

Calendar calendar = Calendar.getInstance();
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int day = calendar.get(Calendar.DAY_OF_MONTH);
MyOnDateSetListener onDateSetListener = new MyOnDateSetListener();
//可以不传参数OnDateSetListener, 第2个参数: int themeResId, 第三个参数:OnDateSetListener
final DatePickerDialog dialog = new DatePickerDialog(context, , null, year, month, day);

dialog.setButton("自定义Button:确定", new DialogInterface.OnClickListener() {
    @Override
    public void onClick(DialogInterface dialog2, int which) {
        DatePicker datePicker = dialog.getDatePicker();
        int year = datePicker.getYear();
        int month = datePicker.getMonth() + ;
        int dayOfMonth = datePicker.getDayOfMonth();
        Log.d(TAG, "日期:" + year + "年" + month + "月" + dayOfMonth + "日");
    }
});
dialog.setButton2("自定义Button:取消", new DialogInterface.OnClickListener() {
    @Override
    public void onClick(DialogInterface dialog, int which) {
        Log.d(TAG, "取消" + ",which=" + which);
    }
});
dialog.setCanceledOnTouchOutside(false);
dialog.setCancelable(false);
dialog.show();
           

TimePickerDialog

TimePickDialog:不重写setButton()

效果图

Android_UI:DialogDialog :Builder模式创建Dialog:构造方法创建DialogFragment仿ios透明加载框系统级的Dialog注意

代码

Calendar calendar = Calendar.getInstance();
int hour = calendar.get(Calendar.HOUR_OF_DAY);
int minute = calendar.get(Calendar.MINUTE);
MyOnTimeSetListener timeSetListener = new MyOnTimeSetListener();

TimePickerDialog dialog = new TimePickerDialog(context, timeSetListener, hour, minute, true);
dialog.setCanceledOnTouchOutside(false);
dialog.setCancelable(false);
dialog.show();
           

TimePickDialog:重写setButton()

效果图

Android_UI:DialogDialog :Builder模式创建Dialog:构造方法创建DialogFragment仿ios透明加载框系统级的Dialog注意

代码

DatePickerDialog

通过方法

getDatePicker()

获取

DatePicker

对象,今儿获取year+month+day,但是

TimePickDialog

没有方法

getTimePicker()

,所以我们不能像DatePickerDialog那样获取hour+minute,那么该怎么做呢,就是修改

SetButton()

的第二个参数,不传

OnClickListener

,直接传入

TimePickDialog

对象。

Calendar calendar = Calendar.getInstance();
int hour = calendar.get(Calendar.HOUR_OF_DAY);
int minute = calendar.get(Calendar.MINUTE);
MyOnTimeSetListener timeSetListener = new MyOnTimeSetListener();
TimePickerDialog dialog = new TimePickerDialog(context, timeSetListener, hour, minute, true);
//有效方法,第2个参数不传OnClickListener,直接传入dialog本身
dialog.setButton("自定义Button:确定", dialog);
dialog.setButton2("自定义Button:取消", dialog);
dialog.setCanceledOnTouchOutside(false);
dialog.setCancelable(false);
dialog.show();
           

MyOnTimeSetListener:

private class MyOnTimeSetListener implements TimePickerDialog.OnTimeSetListener {
    @Override
    public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
        Log.d(TAG, "时间:" + hourOfDay + "时" + minute + "分");
    }
}
           

其它

Demo: http://git.oschina.net/AndroidUI/DatePickerDialogTimePickerDialog

参考:

Android编程之TimePickerDialog设置确定键导致OnTimeSetListener不响应问题

Android:Picker(DatePicker、TimerPicker、NumberPicker)

重写DatePickerDialog 解决OnDateSetListener只有完成,没有取消回调问题

DialogFragment

自定义类继承

DialogFragment

,重写

onCreateDialog()

或者

onCreateView()

创建dialog

第一种:

onCreateDialog()

中创建

dialog

第二种:

onCreateDialog()

中创建

dialog

第三种:在

onCreateView()

中自定义

view

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.frag_dialog_3, container, false);
    return rootView;
}
           

显示dialog

DialogFragment01 frag = new DialogFragment01();
frag.show(getSupportFragmentManager(), "frag");
           

Demo

DialogFragment01

public class DialogFragment01 extends DialogFragment implements View.OnClickListener {

    @NonNull
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        Dialog dialog = super.onCreateDialog(savedInstanceState);
        dialog.setTitle("Title");
        dialog.setContentView(R.layout.frag_dialog_3);
        dialog.setCanceledOnTouchOutside(false);
        dialog.setCancelable(false);

        TextView tv1 = dialog.findViewById(R.id.tv1);
        TextView tv2 = dialog.findViewById(R.id.tv2);
        tv1.setOnClickListener(this);
        tv2.setOnClickListener(this);
        return dialog;
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.tv1:
                Toast.makeText(getActivity(), "tv1", Toast.LENGTH_SHORT).show();
                break;
            case R.id.tv2:
                Toast.makeText(getActivity(), "tv2", Toast.LENGTH_SHORT).show();
                break;
        }
    }
}
           

DialogFragment02

public class DialogFragment02 extends DialogFragment {

    @NonNull
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        AlertDialog dialog = new AlertDialog.Builder(getActivity())
                .setTitle("Title")
                .setMessage("message")
                .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {

                    }
                })
                .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {

                    }
                })
                .setCancelable(false)
                .create();
        dialog.setCanceledOnTouchOutside(false);
        return dialog;
    }
}
           

DialogFragment03

public class DialogFragment03 extends DialogFragment {

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setStyle(DialogFragment.STYLE_NO_TITLE,);//去掉dialog的Title,也可以使用style
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.frag_dialog_3, container, false);
        return rootView;
    }
}
           

Demo:https://git.oschina.net/AndroidUI/dialogfragment01.git

使用DialogFragment怎么把value传给Activity?

采用的接口的方式,让Activity实现给接口,把DialogFragment对象返给Activity

public class NoticeDialogFragment extends DialogFragment {

    private static final String TAG = "Fragment";
    private String[] provinces;
    public String province="京";//默认

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        provinces = ((MainActivity) getActivity()).provinces;
    }

    @NonNull
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity())
                .setTitle(R.string.app_name)
                .setSingleChoiceItems(provinces, -, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        province = provinces[which];
                    }
                })
                .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        mListener.onDialogPositiveClick(NoticeDialogFragment.this);
                    }
                })
                .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        mListener.onDialogNegativeClick(NoticeDialogFragment.this);
                    }
                });
        return builder.create();
    }


    interface DialogListener {
        void onDialogPositiveClick(DialogFragment dialog);

        void onDialogNegativeClick(DialogFragment dialog);
    }

    DialogListener mListener;

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        // Verify that the host activity implements the callback interface
        try {
            // Instantiate the NoticeDialogListener so we can send events to the host
            mListener = (DialogListener) context;
        } catch (ClassCastException e) {
            // The activity doesn't implement the interface, throw exception
            throw new ClassCastException(context.toString()
                    + " must implement NoticeDialogListener");
        }
    }
}
           
@Override
public void onDialogPositiveClick(DialogFragment dialog) {
    Log.d(TAG, ((NoticeDialogFragment)dialog).province);
}

@Override
public void onDialogNegativeClick(DialogFragment dialog) {

}
           

仿ios透明加载框

效果图

Android_UI:DialogDialog :Builder模式创建Dialog:构造方法创建DialogFragment仿ios透明加载框系统级的Dialog注意

工具类

为了方便以后使用,写成工具类。

public class ProgressDialogUtil {

    private static Dialog mDialog;
    private static ProgressDialogUtil dialogUtil;

    private ProgressDialogUtil() {
        super();
    }

    public static ProgressDialogUtil getInstance(Context context) {
        if (mDialog == null) {
            dialogUtil = new ProgressDialogUtil();
            AlertDialog.Builder mBuilder = new AlertDialog.Builder(context, R.style.full_screen_dialog);
            View view = LayoutInflater.from(context).inflate(R.layout.custom_progress_dialog_2, null);
            mBuilder.setView(view);
            mBuilder.setCancelable(true);

            mDialog = mBuilder.create();
            mDialog.setCanceledOnTouchOutside(false);

            Window win = mDialog.getWindow();
            //显示对话框时,后面的Activity不变暗,可选操作。
            win.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);

            //获取对话框当前的参数值,下面代码不加也可以
//            WindowManager.LayoutParams params = win.getAttributes();
//            params.gravity = Gravity.CENTER;
//            win.setAttributes(params);
        }
        return dialogUtil;
    }

    public void showProgressDialog() {
        if (!mDialog.isShowing()) {
            mDialog.show();
        }
    }

    public void dismissProgressDialog() {
        if (mDialog.isShowing()) {
            mDialog.dismiss();
        }
    }
}
           

**R.style.full_screen_dialog**

<style name="full_screen_dialog">
    <item name="android:windowFrame">@null</item>
    <item name="android:windowIsFloating">true</item>
    <item name="android:windowContentOverlay">@null</item>
    <item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
    <item name="android:windowSoftInputMode">stateUnspecified|adjustPan</item>
</style>
           

**R.layout.custom_dialog**

<?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:gravity="center"
    android:background="#78909C"
    android:padding="5dp"
    android:orientation="horizontal">


    <ProgressBar
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="加载中..."
        android:layout_marginLeft="5dp"
        android:textSize="16sp"/>
</LinearLayout>
           

custom_progress_dialog_bg.xml

<?xml version="1.0" encoding="utf-8"?>
  <shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle" >

    <solid android:color="#80000000" />
    <corners android:radius="8dip" />

</shape>
           

显示和隐藏

ProgressDialogUtil.getInstance(context).showProgressDialog();
ProgressDialogUtil.getInstance(context).dismissProgressDialog();
           

WindowManager.LayoutParams.FLAG_DIM_BEHIND

当使用系统的progressDialog时,当前的activity会变暗,这是因为默认的

WindowManager.LayoutParams.FLAG_DIM_BEHIND

,DIM是

dimmed

的缩写,是变暗的意思

二:采用了帧动画

Android_UI:DialogDialog :Builder模式创建Dialog:构造方法创建DialogFragment仿ios透明加载框系统级的Dialog注意

需要复制的内容

下载Demo复制

  • mipmap中的12张图片
  • drawable中2个文件,

    progress_drawable_list.xml

    custom_progress_dialog_bg.xml

  • dialog的自定义布局
  • color
  • style
  • ProgressDialogUtil2

progress_drawable_list.xml 帧动画

<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:drawable="@mipmap/app_loading_001"
        android:duration="100"/>
    <item
        android:drawable="@mipmap/app_loading_002"
        android:duration="100"/>
    <item
        android:drawable="@mipmap/app_loading_003"
        android:duration="100"/>
    <item
        android:drawable="@mipmap/app_loading_004"
        android:duration="100"/>
    <item
        android:drawable="@mipmap/app_loading_005"
        android:duration="100"/>
    <item
        android:drawable="@mipmap/app_loading_006"
        android:duration="100"/>
    <item
        android:drawable="@mipmap/app_loading_007"
        android:duration="100"/>
    <item
        android:drawable="@mipmap/app_loading_008"
        android:duration="100"/>
    <item
        android:drawable="@mipmap/app_loading_009"
        android:duration="100"/>
    <item
        android:drawable="@mipmap/app_loading_0010"
        android:duration="100"/>
    <item
        android:drawable="@mipmap/app_loading_0011"
        android:duration="100"/>
    <item
        android:drawable="@mipmap/app_loading_0012"
        android:duration="100"/>
</animation-list>
           

ProgressDialogUtil2

public class ProgressDialogUtil2 {
    private static ProgressDialogUtil2 instance = null;
    private static Dialog dialog;
    private static View view;
    private TextView tv;

    public synchronized static ProgressDialogUtil2 getInstance(Context context) {

        if (instance == null) {
            instance = new ProgressDialogUtil2();
            dialog = new Dialog(context, R.style.CustomDialogStyle);
            view = LayoutInflater.from(context).inflate(R.layout.custom_progress_dialog_1, null);
            dialog.setContentView(view);

            ImageView progressImageView = (ImageView) view.findViewById(R.id.iv_loading);
            AnimationDrawable animationDrawable = (AnimationDrawable) progressImageView.getDrawable();
            animationDrawable.start();

            //要放在动画后面,否则无效
            dialog.setCanceledOnTouchOutside(false);
        }
        return instance;
    }

    public void show() {
        dialog.show();
    }

    public void showstr(String str) {
        if (tv == null) {
            tv = (TextView) view.findViewById(R.id.tv_loading);
            tv.setText(str);
        } else {
            tv.setText(str);
        }
        dialog.show();
    }

    public void cancle() {
        if (dialog == null) {
            return;
        } else {
            dialog.cancel();
        }
    }
}
           

显示和隐藏

ProgressDialogUtil2.getInstance(context).show();
ProgressDialogUtil2.getInstance(context).cancle();
           

Demo: http://git.oschina.net/AndroidUI/customdialog01

系统级的Dialog

我们都知道dialog是依赖activity而存在的,但是系统级的Dialog不依赖Activity,所以当按下Button的同时,我们弹出此Dialog,同时进入MainActivity2页面,这是会发现,在activity的切换过程中,Dialog一直都存在。

效果图

Android_UI:DialogDialog :Builder模式创建Dialog:构造方法创建DialogFragment仿ios透明加载框系统级的Dialog注意

权限+Type

需要权限:

需要设置

TYPE_SYSTEM_ALERT

设置完type后,在360、小米、魅族手机上

dialog

仍然不显示,这是因为厂家对系统走了修改,解决方方法是在设置

TYPE_TOAST

下面来自android不用context弹dialog

无意中用了一个4.0系统(<19)的手机测试了一下,dialog能弹出来,但是界面里面的button根本不能点击!这就尴尬了!经过一番资料的查找问题终于找到了:

1.WindowManager.LayoutParams.TYPE_TOAST仅在 API level >= 19 时可以正常显示,API level 19 以下因无法接收无法接收触摸(点击)和按键事件!

2.API level 19 后做了调整,当我们使用 TYPE_TOAST, Android 会偷偷给我们加上 FLAG_NOT_FOCUSABLE 和 FLAG_NOT_TOUCHABLE , 4.0.1 开始, 会额外再去掉FLAG_WATCH_OUTSIDE_TOUCH。 这样真的是什么事件都没了。

3.对于 API level < 19 的机器(MIUI除外),想要达到目的,需要:

a.要有 android.permission.SYSTEM_ALERT_WINDOW 权限

b.将 type 设置为 WindowManager.LayoutParams.TYPE_PHONE 或者 WindowManager.LayoutParams.TYPE_SYSTEM_ALERT

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
    //解决Android 起不能再用Toast的问题(先解决crash)
    if(Build.VERSION.SDK_INT > ){
        md.getWindow().setType(WindowManager.LayoutParams.TYPE_PHONE);
    }else{
        md.getWindow().setType(WindowManager.LayoutParams.TYPE_TOAST);
    }
} else {
    md.getWindow().setType(WindowManager.LayoutParams.TYPE_PHONE);
}
           

其它

参考:android不用context弹dialog

Demo:https://git.oschina.net/AndroidUI/buglyupdate01

注意

dialog的Context不能使用

getApplicationContext()

dialog

中不能使用

getApplicationContext()

,会报错。因为

dialog

是依附于

activity

而存在的。

dialog.setCanceledOnTouchOutside(false)无效

原因:

1. 在dialog.show()之前调用无效

2. 自定义的dialog有动画

animation-list

也会导致其无效

解决方法:

在show()后面

dialog.show();
dialog.setCanceledOnTouchOutside(false);
           

在动画后面

AnimationDrawable animationDrawable = (AnimationDrawable) progressImageView.getDrawable();
animationDrawable.start();
dialog.setCanceledOnTouchOutside(false);