Android开发之DialogFragment用法实例总结
本文实例讲述了android开发之dialogfragment用法。分享给大家供大家参考,具体如下:
背景
android 官方推荐使用 dialogfragment 来代替 dialog ,可以让它具有更高的可复用性(降低耦合)和更好的便利性(很好的处理屏幕翻转的情况)。
而创建 dialogfragment 有两种方式:
1. 覆写其 oncreatedialog
方法 — ①
2. 覆写其 oncreateview
方法 — ②
虽然这两种方式都能实现相同的效果,但是它们各有自己适合的应用场景:
1. 方法 ①,一般用于创建替代传统的 dialog 对话框的场景,ui 简单,功能单一。
2. 方法 ②,一般用于创建复杂内容弹窗或全屏展示效果的场景,ui 复杂,功能复杂,一般有网络请求等异步操作。
应用
基本用法
对于方法 ①,创建一个 dialog 并返回它即可:
@override public dialog oncreatedialog(bundle savedinstancestate) { //为了样式统一和兼容性,可以使用 v7 包下的 alertdialog.builder alertdialog.builder builder = new alertdialog.builder(getactivity()); // 设置主题的构造方法 // alertdialog.builder builder = new alertdialog.builder(getactivity(), r.style.customdialog); builder.settitle("注意:") .setmessage("是否退出应用?") .setpositivebutton("确定", null) .setnegativebutton("取消", null) .setcancelable(false); //builder.show(); // 不能在这里使用 show() 方法 return builder.create(); }
当然,你也可以使用自定义 view 来创建:
@override public dialog oncreatedialog(bundle savedinstancestate) { alertdialog.builder builder = new alertdialog.builder(getactivity()); // 设置主题的构造方法 // alertdialog.builder builder = new alertdialog.builder(getactivity(), r.style.customdialog); layoutinflater inflater = getactivity().getlayoutinflater(); view view = inflater.inflate(r.layout.fragment_dialog, null); builder.setview(view) // do someting,eg: textview tv = view.findviewbyid(r.id.tv); return builder.create(); }
ps:创建 dialog 的方式有多种,比如下面这种,使用时略有差异,需要自己注意:
@override public dialog oncreatedialog(bundle savedinstancestate) { layoutinflater inflater = getactivity().getlayoutinflater(); view view = inflater.inflate(r.layout.fragment_dialog, null); dialog dialog = new dialog(getactivity()); // 设置主题的构造方法 // dialog dialog = new dialog(getactivity(), r.style.customdialog); dialog.setcontentview(view); // do someting return dialog; }
对于方法 ②,和普通的 fragment 用法基本一致:
@override public view oncreateview(layoutinflater inflater, viewgroup container, bundle savedinstancestate) { view rootview = inflater.inflate(r.layout.fragment_dialog, container, false); // do someting return rootview; } /** * 设置主题需要在 oncreate() 方法中调用 setstyle() 方法 */ @override public void oncreate(@nullable bundle savedinstancestate) { super.oncreate(savedinstancestate); setstyle(dialogfragment.style_no_title, r.style.customdialog); }
处理屏幕翻转
如果使用传统的 dialog ,需要我们手动处理屏幕翻转的情况,但使用 dialogfragment 的话,则不需要我们进行任何处理,fragmentmanager 会自动管理 dialogfragment 的生命周期。
无标题栏/全屏
在基本用法里代码注释有设置主题的地方,下面详细说下两种方法下设置无标题栏和实现全屏的方式:
无标题栏
对于方法 ① :
@override public dialog oncreatedialog(bundle savedinstancestate) { layoutinflater inflater = getactivity().getlayoutinflater(); view view = inflater.inflate(r.layout.fragment_dialog, null); dialog dialog = new dialog(getactivity(), r.style.customdialog); // 关闭标题栏,setcontentview() 之前调用 dialog.requestwindowfeature(window.feature_no_title); dialog.setcontentview(view); dialog.setcanceledontouchoutside(true); return dialog; }
对于方法 ②:
@override public void oncreate(@nullable bundle savedinstancestate) { super.oncreate(savedinstancestate); /** * setstyle() 的第一个参数有四个可选值: * style_normal|style_no_title|style_no_frame|style_no_input * 其中 style_no_title 和 style_no_frame 可以关闭标题栏 * 每一个参数的详细用途可以直接看 android 源码的说明 */ setstyle(dialogfragment.style_no_title, r.style.customdialog); }
实现全屏(宽/高度全屏)
常用的形式大多是宽度上和屏幕一样宽,高度自适应,下面直接看代码:
方法 ① :
@override public dialog oncreatedialog(bundle savedinstancestate) { layoutinflater inflater = getactivity().getlayoutinflater(); view view = inflater.inflate(r.layout.fragment_dialog, null); dialog dialog = new dialog(getactivity(), r.style.customdialog); dialog.requestwindowfeature(window.feature_no_title); dialog.setcontentview(view); dialog.setcanceledontouchoutside(true); //do something // 设置宽度为屏宽、位置靠近屏幕底部 window window = dialog.getwindow(); window.setbackgrounddrawableresource(r.color.transparent); windowmanager.layoutparams wlp = window.getattributes(); wlp.gravity = gravity.bottom; wlp.width = windowmanager.layoutparams.match_parent; wlp.height = windowmanager.layoutparams.wrap_content; window.setattributes(wlp); return dialog; }
代码 12 行设置了窗口的背景色为透明,这一步是必须的;
代码 15 行设置窗口的宽度为 match_parent,效果是和屏幕宽度一样大,同样你也可以设置高度的值。设置宽度和高度除了 match_parent 和 wrap_content ,也可以直接设置成具体的数值。
方法 ②:
@override public void oncreate(@nullable bundle savedinstancestate) { super.oncreate(savedinstancestate); setstyle(dialogfragment.style_no_title, r.style.customdialog); } @override public view oncreateview(layoutinflater inflater, viewgroup container, bundle savedinstancestate) { getdialog().setcanceledontouchoutside(true); view rootview = inflater.inflate(r.layout.fragment_dialog, container, false); //do something // 设置宽度为屏宽、靠近屏幕底部。 final window window = getdialog().getwindow(); window.setbackgrounddrawableresource(r.color.transparent); window.getdecorview().setpadding(0, 0, 0, 0); windowmanager.layoutparams wlp = window.getattributes(); wlp.gravity = gravity.bottom; wlp.width = windowmanager.layoutparams.match_parent; wlp.height = windowmanager.layoutparams.wrap_content; window.setattributes(wlp); return rootview; }
代码 14 行设置了窗口的背景色为透明,这一步是必须的;
代码 15 行设置了窗口的 pading 值全部为0,这一步也是必须的,内容不能填充全部宽度和高度。
其他的和 ① 中的类似。
应用场景区别
文章一开始简单总结了方法 ① 和方法 ② 的应用场景,这里说明下:
1. 从基本的用法中可以看到方法 ① 为简单的替代 dialog 提供了非常方便的创建方式,比方法 ② 有优势
2. 方法 ① 在使用了多线程(例如网络请求)的情况下,不能正确的获取当前 fragment 的状态,会产生空指针异常。方法 ② 则没有此问题,而且,其创建方式默认使用了自定义 view,更便于应对复杂 ui 的场景。
这里举例说明:方法 ① 和方法 ② 的//do something
代码处,我们进行一些异步操作:
textview title = rootview.findviewbyid(r.id.dialoag_tv); title.settext("value a"); new sometask().execute(url); private class sometask extends asynctask<string, void, boolean> { @override protected boolean doinbackground(string... params) { // 一些网络请求 // 成功时 return true; // 异常时 return false; } @override protected void onpostexecute(boolean aboolean) { super.onpostexecute(aboolean); // if (!isvisible()) return; if (aboolean) { title.settext("value b"); } } }
如果在网络请求未结束或者刚结束时关闭了当前 dialogfragment ,代码 19 行就会报空指针异常了,代码 17 的作用就是判断 dialogfragment 当前的状态是否为可用态,但是 isvisible()
以及 ishide()
对于方法 ① 无法正确返回其状态,方法 ② 则正常。方法 ① 和方法 ② 创建 dialogfragment 的一些状态并不是完全一致。
ps:你也可以使用静态 handler 结合弱引用等来处理异步操作,那样对 dialogfragment 状态的获取就不重要了。
总结
以上是个人在实际开发过程中的一点总结和看法,希望你能抱着存疑的态度进行尝试,如果有新的观点或者文章中有不正确的地方,欢迎和我联系。
更多关于android相关内容感兴趣的读者可查看本站专题:《android开发入门与进阶教程》、《android调试技巧与常见问题解决方法汇总》、《android基本组件用法总结》、《android视图view技巧总结》、《android布局layout技巧总结》及《android控件用法总结》
希望本文所述对大家android程序设计有所帮助。