一、DialogFragment基础
参考自谷歌安卓文档
1、实现类继承自DialogFragment类
2、必须重写onCreateView
或onCreateDialog
方法,onCreateView
可以自定义对话框,onCreateDialog
使用默认对话框
3、DialogFragment包含Dialog.setOnCancelListener()
和Dialog.setOnDismissListener()
回调,可在取消或清除对话框时自定义操作
4、利用bundle
和setArguments()
、getArguments()
方法,实现Fragment或Activity与Dialogfragment间的参数传递
二、DialogFragment使用代码示例
1、自定义DialogFragment类
DataBinding,ViewModel与DialogFragment结合
public class mDialog extends DialogFragment {
//DialogFragment的构造函数方法体需要为空
//创建对象写在newInstance方法中
public static mDialog newInstance(Equipment item) {
DialogCurtain fragment = new mDialog ();
Bundle bundle = new Bundle();
bundle.putSerializable(Equipment.curtain, item);
fragment.setArguments(bundle);
return fragment;
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
binding = DataBindingUtil.inflate(inflater, R.layout.item_operate_curtain_motion, container, false);
binding.setLifecycleOwner(this);
viewModel = new ViewModelProvider(getActivity()).get(EquipmentViewModel.class);
Bundle bundle = getArguments();
if (bundle != null) {
item = (Equipment) bundle.getSerializable(Equipment.curtain);
}
return binding.getRoot();
}
2、在OnStart()
或OnResume()
回调中对自定义对话框进行显示设置
@Override
public void onStart() {
Dialog dialog = getDialog();
if (dialog != null) {
Window window = getDialog().getWindow();
window.setBackgroundDrawable(new ColorDrawable(Color.BLACK));
//设置背景透明度
window.setDimAmount(0.75F);
DisplayMetrics dm = new DisplayMetrics();
getActivity().getWindowManager().getDefaultDisplay().getMetrics(dm);
WindowManager.LayoutParams attributes = dialog.getWindow().getAttributes();
dialog.getWindow().setAttributes(attributes);
//自定义对话框显示比例
dialog.getWindow().setLayout((int) (dm.widthPixels * 0.4), (int) (dm.heightPixels * 0.75));
}
super.onStart();
}
3、Fragment中显示DialogFragment
开启Fragment事务,将DialogFragment加到回退栈中
show()
方法进行显示
private fun showDialog(str: String, item: Equipment) {
val ft: FragmentTransaction = parentFragmentManager.beginTransaction()
val prev: Fragment? = getFragmentManager()?.findFragmentByTag("dialog")
if (prev != null) {
ft.remove(prev)
}
ft.addToBackStack(null)
val newFragment: mDialog= mDialog.newInstance(item)
newFragment.show(ft, "dialog")
}
}
三、DialogFragment点击背景取消对话框与底部导航栏冲突
产品提出需求如下:
点击对话框布局的关闭按钮和对话框空白处背景,都可以取消对话框。
在开发过程中,发现外部点击事件失效,原因在于
window.addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
借鉴https://www.jianshu.com/p/6d48fd0ce177
通过这句话屏蔽了底部导航栏,但这个属性使背景区域的点击事件穿透到底层View。
于是进行如下处理:
dialog.setOnShowListener(v -> {
dialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
Utils.hideSystemUI(dialog.getWindow().getDecorView());
});
当对话框显示之后取消当时Flag。
另外通过对dismiss()方法的监听可在对话框消失时进行一些刷新操作
dialog.setOnDismissListener(v -> {
Handler handler = new Handler();
handler.postDelayed(() -> {
EventBus.getDefault().post(new EquipmentEvent("Dialog dismiss"));
}, 500);
});
网友评论