DialogFragment 创建对话框
前言:
在创建对话框我们通常能想到的是 AlertDialog 和 Dialog 和 PopupWindow, 但是在Android 3.0只有我们引入了
DialogFragment , DialogFragment 是一种特殊的Fragment, Android 官方推荐使用 DialogFragment 来代替 Dialog ,可以让它具有更高的可复用性(降低耦合)和更好的便利性(很好的处理屏幕翻转的情况.
应用
DialogFragment 的创建:
一、 创建 DialogFragment 有两种方式:
- 覆写其 onCreateDialog 方法 — ①
- 覆写其 onCreateView 方法 — ②
对于方法 ①的创建 创建一个 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();
}
创建 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 一样, 不过要注意Fragment的生命周期,另外DialogFragment 默认是有Title 的,注意根据需要设置
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);
}
常见问题处理
- 屏幕旋转问题
当屏幕旋转时,如果用户未做任何限定,视图中所有的空间和容器多会进行销毁和重新创建,因此当前情况下弹出对话框, 如果屏幕旋转,之前对话框中的内容都会丢失,因此,正常情况都需要处理这个问题,但是现在用DialogFramt 来做对话框, 就可以完全不用考虑这个问题了,FragmentManager 会自动管理 DialogFragment 的生命周期。 - 标题栏/全屏
@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);
}
- DialogFragment做屏幕适配
- 可以根据实际情况 ,将DialogFragment 以弹窗显示, 或者以直接嵌入到页面中
public void showDialogInDifferentScreen(View view)
{
FragmentManager fragmentManager = getFragmentManager();
EditNameDialogFragment newFragment = new EditNameDialogFragment();
boolean mIsLargeLayout = getResources().getBoolean(R.bool.large_layout) ;
Log.e("TAG", mIsLargeLayout+"");
if (mIsLargeLayout )
{
// The device is using a large layout, so show the fragment as a
// dialog
newFragment.show(fragmentManager, "dialog");
} else
{
// The device is smaller, so show the fragment fullscreen
FragmentTransaction transaction = fragmentManager
.beginTransaction();
// For a little polish, specify a transition animation
transaction
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
// To make it fullscreen, use the 'content' root view as the
// container
// for the fragment, which is always the root view for the activity
transaction.replace(R.id.id_ly, newFragment)
.commit();
}
}
效果:
[图片上传失败...(image-94ef89-1563373384992)]
](https://img.haomeiwen.com/i5900919/ddd267269cba6437.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
- 默认情况下Dialog 样式,宽度充满屏幕,左右保留一些外边距。如果在DialogFragment 的布局文件中做限定并没有太大作用,DialogFragment 会根据布局中自适应调整
那么此时,我们需要 在代码中通过设置Dialog来进行限定
getDialog().getWindow().setLayout(width, height); - 对话框圆角
如果要实现自定义对话框圆角,可以加入下面的代码使对话框背景透明
然后将自定义布局设置为圆角就可以了,在drawable目录中定义XML如下,根布局background属性设置为该xml就可以了。
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="8dp"/>
<stroke android:color="#FDFFFFFF"/>
<solid android:color="#FDFFFFFF"/>
</shape>
DialogFragment 的一些设置
这里我就不做详细介绍, 可以参考
https://blog.csdn.net/angcyo/article/details/50613084
个人总结
- 和传统的Dialog相比, Fragment有更多的生命周期,处理复杂的逻辑更有优势,另外不需要处理屏幕旋转问题
- 两种方式都能实现相同的效果,但是它们各有自己适合的应用场景:
方法 ①,一般用于创建替代传统的 Dialog 对话框的场景,UI 简单,功能单一。
方法 ②,一般用于创建复杂内容弹窗或全屏展示效果的场景,UI 复杂,功能复杂,一般有网络请求等异步操作。
应用场景区别
参考链接
https://likfe.com/2016/10/27/dialog-fragment/
https://blog.csdn.net/angcyo/article/details/50613084
https://blog.csdn.net/lmj623565791/article/details/37815413