简介
官方推荐使用的Dialog类型,继承自Fragment,通过FragmentManager管理对话弹框。由于继承自Fragment,使用dialog时完全可以将其看作Fragment。
使用DialogFragment需要实现onCreateView()、onCreateDialog()其中之一。
onCreateView即将完全自定义一个dialog。
onCreateDialog即重用Dialog样式,仅用此管理dialog。
好处:
1. 旋转屏幕、按下后退键时 等情况可以更好的管理其声明周期。
2. 提供方法将Dialog作为内嵌的组件进行重用
实现:
就将其完全当作一个Fragment来使用就OK了,这里就不贴代码了。。。
注意点
1.去掉dialog的title
在onCreateView方法中添加getDialog().requestWindowFeature(Window.FEATURE_NO_TITLE);
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
getDialog().requestWindowFeature(Window.FEATURE_NO_TITLE);
View inflate = inflater.inflate(R.layout.dialog_picture_verfy, container);
ButterKnife.inject(this, inflate);
return inflate;
}
2.Activity传参到Dialog
使用Fragment的传参方式
public static PictureVerfyDialog newInstance(FaFaIMMessageModel fafaModel) {
Bundle args = new Bundle();
args.putSerializable(PARAM_FAFA_MESSAGE, fafaModel);
PictureVerfyDialog fragment = new PictureVerfyDialog();
fragment.setArguments(args);
return fragment;
}
3.物理返回键不消失
onCreate()方法中调用:
this.setCancelable(false);
onCreateDialog方式:
点击外部不消失的方法:getDialog.setCanceledOnTouchOutside(false);
对于点击返回键不消失,需要监听OnKeyListener:
getDialog().setOnKeyListener(new DialogInterface.OnKeyListener() {
@Override
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
return true;
}
return false;
}
});
4.传递数据给Activity
类似fragment,通过Interface外抛的方式传递数据
/**
* 1. 创建监听接口
*
* @author fengzhen
* @version v5.2.4, 2017/6/22 18:36
*/
public interface OnDismissListener {
void onDismiss();
}
// 2. 内部属性
private OnDismissListener mOnDismissListener;
/**
* 3. 设置监听接口, activity中调用此方法进行设置
*
* @author fengzhen
* @version v5.2.4, 2017/6/22 18:38
*/
public void setmOnDismissListener(OnDismissListener mOnDismissListener) {
this.mOnDismissListener = mOnDismissListener;
}
// 4. 具体的使用,调用activity中的接口的具体实现方法
public void onDismiss() {
if (mOnDismissListener != null){
mOnDismissListener.onDismiss();
}
}
5.抛出异常:IllegalStateException
调用show()方法抛出此异常
IllegalStateException: Can not perform this action after onSaveInstanceState
解决方式:
官方提供了方法:
/** {@hide} */
public void showAllowingStateLoss(FragmentManager manager, String tag) {
mDismissed = false;
mShownByMe = true;
FragmentTransaction ft = manager.beginTransaction();
ft.add(this, tag);
ft.commitAllowingStateLoss();
}
但是很心机的hide了,这里通过反射的方式,强行执行这个方法的内容。
/**
* 使用反射重写showAllowingStateLoss()方法
* 解决调用show()方法异常
*
* @author fengzhen
* @version v5.2.4, 2017/7/2 17:29
*/
public void showAllowingStateLoss(FragmentManager manager, String tag) {
try {
Field mDismissed = DialogFragment.class.getDeclaredField("mDismissed");
mDismissed.setAccessible(true);
mDismissed.set(this,false);
Field mShownByMe = DialogFragment.class.getDeclaredField("mShownByMe");
mShownByMe.setAccessible(true);
mShownByMe.set(this,true);
} catch (Exception e) {
e.printStackTrace();
}
FragmentTransaction ft = manager.beginTransaction();
ft.add(this, tag);
ft.commitAllowingStateLoss();
}
注意不能直接把@hide的方法反射出来调用,所以下面的方法抛出异常 NosuchMethodException:
public void showAllowingStateLoss(FragmentManager manager, String tag) {
try {
Method showAllowingStateLoss = DialogFragment.class.getDeclaredMethod("showAllowingStateLoss", FragmentManager.class, String.class);
showAllowingStateLoss.setAccessible(true);
showAllowingStateLoss.invoke(this, manager, tag);
} catch (Exception e) {
e.printStackTrace();
}
}
补充
1. 反射中:getDeclaredMethod()、getMethod区别
getDeclaredMethod():类自身声明的所有方法
getMethod():获取的是public方法
2.反射中:private的属性
赋值之前setAccessible(true),设定为可以修改。