簡介
官方推薦使用的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),設定爲可以修改。