2019-03-10 14:19:10.971 22626-22626/org.lym.sourcecodeparse D/DialogFragment: onAttach
2019-03-10 14:19:10.971 22626-22626/org.lym.sourcecodeparse D/DialogFragment: onCreate
2019-03-10 14:19:10.972 22626-22626/org.lym.sourcecodeparse D/DialogFragment: onCreateDialog
2019-03-10 14:19:10.994 22626-22626/org.lym.sourcecodeparse D/DialogFragment: onActivityCreated
2019-03-10 14:19:11.186 22626-22626/org.lym.sourcecodeparse D/DialogFragment: onStart
2019-03-10 14:19:11.186 22626-22626/org.lym.sourcecodeparse D/DialogFragment: onResume
从上面打印的回调生命周期方法来看,我们是可以在onStart方法中对Dialog进行属性设置的,具体代码如下:
@Override
public void onStart() {
super.onStart()
Dialog dialog = getDialog()
Window window = dialog.getWindow()
if (window == null) {
return
WindowManager.LayoutParams attributes = window.getAttributes()
//设置Dialog窗口的高度
attributes.height = WindowManager.LayoutParams.MATCH_PARENT
//设置Dialog窗口的宽度
attributes.width = WindowManager.LayoutParams.MATCH_PARENT
//设置Dialog的居中方向
attributes.gravity = Gravity.CENTER
//设置Dialog弹出时背景的透明度
attributes.dimAmount = 0.6f
//设置Dialog水平方向的间距
attributes.horizontalMargin = 0f
//设置Dialog垂直方向的间距
attributes.verticalMargin = 0f
//设置Dialog显示时X轴的坐标,具体屏幕X轴的偏移量
attributes.x = 0
//设置Dialog显示时Y轴的坐标,距离屏幕Y轴的偏移量
attributes.y = 0
//设置Dialog的透明度
attributes.alpha = 0f
//设置Dialog显示和消失时的动画
attributes.windowAnimations = 0
window.setAttributes(attributes)
Logger.d(TAG, "onStart")
复制代码
三、DialogFragmeng源码分析
1.下面先贴一下DialogFragment的部分源码,并进行简要分析。
public class DialogFragment extends Fragment implements OnCancelListener, OnDismissListener {
boolean mViewDestroyed;
boolean mDismissed;
boolean mShownByMe;
public DialogFragment() {
public void show(FragmentManager manager, String tag) {
this.mDismissed = false;
this.mShownByMe = true;
FragmentTransaction ft = manager.beginTransaction();
ft.add(this, tag);
ft.commit();
public int show(FragmentTransaction transaction, String tag) {
this.mDismissed = false;
this.mShownByMe = true;
transaction.add(this, tag);
this.mViewDestroyed = false;
this.mBackStackId = transaction.commit();
return this.mBackStackId;
public void showNow(FragmentManager manager, String tag) {
this.mDismissed = false;
this.mShownByMe = true;
FragmentTransaction ft = manager.beginTransaction();
ft.add(this, tag);
ft.commitNow();
public void dismiss() {
this.dismissInternal(false);
public void dismissAllowingStateLoss() {
this.dismissInternal(true);
void dismissInternal(boolean allowStateLoss) {
if (!this.mDismissed) {
this.mDismissed = true;
this.mShownByMe = false;
if (this.mDialog != null) {
this.mDialog.dismiss();
this.mViewDestroyed = true;
if (this.mBackStackId >= 0) {
this.getFragmentManager().popBackStack(this.mBackStackId, 1);
this.mBackStackId = -1;
} else {
FragmentTransaction ft = this.getFragmentManager().beginTransaction();
ft.remove(this);
if (allowStateLoss) {
ft.commitAllowingStateLoss();
} else {
ft.commit();
@NonNull
public Dialog onCreateDialog(Bundle savedInstanceState) {
return new Dialog(this.getActivity(), this.getTheme());
public void onDismiss(DialogInterface dialog) {
if (!this.mViewDestroyed) {
this.dismissInternal(true);
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (this.mShowsDialog) {
View view = this.getView();
if (view != null) {
if (view.getParent() != null) {
throw new IllegalStateException("DialogFragment can not be attached to a container view");
this.mDialog.setContentView(view);
Activity activity = this.getActivity();
if (activity != null) {
this.mDialog.setOwnerActivity(activity);
this.mDialog.setCancelable(this.mCancelable);
this.mDialog.setOnCancelListener(this);
this.mDialog.setOnDismissListener(this);
if (savedInstanceState != null) {
Bundle dialogState = savedInstanceState.getBundle("android:savedDialogState");
if (dialogState != null) {
this.mDialog.onRestoreInstanceState(dialogState);
复制代码
2.源码分析总结
可以重写onCreateDialog或者onCreateView来创建DialogFragment的视图,但是onCretaeView的优先级要高于onCreateDilaog,所以没有特殊的需要,一般通过重写onCreateView来创建Dialog的视图即可。
从一开始我们就打印了DialogFragment从创建视图到show出来回调的一系列生命周期方法,我们得知设置dialog的属性可以在DialogFragment中的onStar回调中进行。
对于dialog的显示我们通过查看源码得知一共有三个方法,show()方法传入一个fragmentManager以及一个tag,showNow方法,传入一个fragmentManger和一个tag,show()方法,传入一个事务和一个tag,并返回该事务中回退栈的id,在调用dismissInternal()方法时,会根据显示DialogFragment的类型来操作DialogFragment出栈。
DialogFragment会在onActivityCreate()中对Dialog的内容试图进行一次赋值,如果你重写了onCrateView方法,并返回了一个不为空的实例,那么将会作为该Dialog的内容视图,然后再对dialog设置了是否可取消,消失监听,以及取消监听
通过上面的源码简析,我们得知在DialogFragment消失时,只会将dialog给隐藏,并不会讲DialogFragment移除栈内,如果想讲DialogFragment在dialog消失时移除栈内,那么需要手动调用dismissInternal()方法
四、细节注意事项
可以通过重写onCreateDialog和onCreateView来设置DialogFragment的视图,但onCraeteView设置的视图优先级要高于在onCreateDialog。
设置Dialog的属性需要在onCreateDialog回调后设置,不然getDialog得到的对象则会是null,推荐在onStar方法中对Dialog进行属性设置。
DialogFragment单个实例只能show一次DialogFrament,如果多次展示的话,则会抛出如下异常
Process: org.lym.sourcecodeparse, PID: 27108
java.lang.IllegalStateException: Fragment already added: DialogFragment{8262d74
at android.support.v4.app.FragmentManagerImpl.addFragment(FragmentManager.java:1893)
at android.support.v4.app.BackStackRecord.executeOps(BackStackRecord.java:760)
at android.support.v4.app.FragmentManagerImpl.executeOps(FragmentManager.java:2595)
at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2382)
at android.support.v4.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2337)
DialogFragment在正常Dismiss后并不会直接从当前的栈中移除,而是在DialogFragment中的onDestroyView()回调时,才会对DialogFragment进行出栈操作,所以如果你如果需要在Activity中频繁的显示隐藏一个DialogFragment,那么在dismiss时需要手动的调用dismissAllowingStateLoss()方法,并且再次show时不能用上一个DialogFragment实例。
DialogFragment并没有对Dialog的消失提供监听给调用者使用,但是我们通过源码分析得知,DialogFragment在onActivityCreate当中其实已经帮我们设置了onDismissListener,所以我们如果需要对Dialog的消失进行监听的话只需重写onDismiss方法即可,还有一种方式则是覆盖父类设置的onDismissListener监听,但是需注意的时,这个监听的复写,必须在父类onActivityCreate方法调用之后,关于消失监听的两种写法如下:
@Override
public void onDismiss(DialogInterface dialog) {
super.onDismiss(dialog);
mListener.onDismiss(dialog);
Logger.d(TAG, "onDismiss");
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (getDialog() != null && null != mListener) {
getDialog().setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
ToastUtils.showToast("覆盖后的OnDismiss Listener");
Logger.d(TAG, "onActivityCreated");
结语:以上便是全文的内容,是自己在使用DialogFragment中碰到了一些坑以及学习后的一些理解,希望能对您有帮助。