最近一直在看Fragment相关的内容,恰好今天项目利用到了DialogFragment,DialogFragment从3.0系统开始支持,更低版本可以使用support library。
使用DialogFragment主要重写onCreateDialog方法或者重写Fragment的onCreate View方法
问题:展示的DialogFragment有一段空白标题,setStyle有notitle属性设置但是会有报错(需要在onCreate中调用),方案:在OnCreateDialog创建Dialog时调用requestWindowFeature(Window.XXXX)
在DialogFragment中可以重写DialogFragment类的onCreateDialog和Fragment类的OnCreateView方法,一般只是自定义对话框布局可以在onCreateView中处理,
onCreateDialog中可以自己实现dialog,这两个一般实现一个就可以满足需求,两个方法可以同时重写,但是这种用法比较鸡肋;使用setStyle报AndroidRuntimeException: requestFeature() must be called before adding content,这是因为在DialogFragment的getLayoutInflater方法中如果设置的style是notable,no frame或no input时会调用
dialog的requestWindowFeature方法
public final boolean requestWindowFeature(int featureId) { return getWindow().requestFeature(featureId); }
下面是requestFeature的注释,必须在窗口设置布局之前调用,所以如果在onCreateDialog中调用setStyle设置这三种样式,会报错;之所以普通重写
onCreateDialog不会报错是因为默认style是Normal类型;若要设置对话框样式可以直接设置dialog.requestWindowFeature
Enable extended screen features. This must be called before * setContentView(). May be called as many times as desired as long as it * is before setContentView().
在返回AlertDialog时重写OnCreateView也会报错,这是因为在Builder.create的时候并没有setContentView,在alertDialog.show时会调用
Alert Dialog的onCreate,会有alertController.installContent调用,在这个方法里调用requestWindowFeature和setContentView;而show
方法是在Fragment的onStart方法中调用的,在此之前如果重写onCreateView就会在OnActivityCreate回调中setContentView,也就是在setContentView
之后调用了requestWindowFeature
零散知识点:1.ScrollView有更多内容待展示,setEdgeFadingHeight
2.TextView.setScroller
DialogFragment原理
public void show(FragmentManager manager, String tag) { mDismissed = false; mShownByMe = true; FragmentTransaction ft = manager.beginTransaction(); ft.add(this, tag); ft.commit(); }
1.这里调用的是add(Fragment f, String tag)这个方法不会把Fragment添加到Activity 的布局结构里,我们一般使用的是
FragmentTransaction add(int containerViewId, Fragment fragment);
在Fragment生命周期OnCreate和onCreateView之间有一个performCreateView的调用f.mContainer = container; f.mView = f.performCreateView(f.getLayoutInflater( f.mSavedFragmentState), container, f.mSavedFragmentState); if (f.mView != null) {2.performCreateView中调用了OnCreateView生命周期回调,在DialogFragment中重写了getLayoutInflater方法创建dialog;public LayoutInflater getLayoutInflater(Bundle savedInstanceState) { if (!mShowsDialog) { return super.getLayoutInflater(savedInstanceState); } mDialog = onCreateDialog(savedInstanceState); switch (mStyle) { case STYLE_NO_INPUT: mDialog.getWindow().addFlags( WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE); // fall through... case STYLE_NO_FRAME: case STYLE_NO_TITLE: mDialog.requestWindowFeature(Window.FEATURE_NO_TITLE); } if (mDialog != null) { return (LayoutInflater)mDialog.getContext().getSystemService( Context.LAYOUT_INFLATER_SERVICE); } return (LayoutInflater) mHost.getContext().getSystemService( Context.LAYOUT_INFLATER_SERVICE); }3.在onActivityCreated设置布局,在onStart弹出Dialogpublic void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); if (!mShowsDialog) { return; } View view = getView(); if (view != null) { if (view.getParent() != null) { throw new IllegalStateException("DialogFragment can not be attached to a container view"); } mDialog.setContentView(view); } mDialog.setOwnerActivity(getActivity()); mDialog.setCancelable(mCancelable); if (!mDialog.takeCancelAndDismissListeners("DialogFragment", this, this)) { throw new IllegalStateException( "You can not set Dialog's OnCancelListener or OnDismissListener"); } if (savedInstanceState != null) { Bundle dialogState = savedInstanceState.getBundle(SAVED_DIALOG_STATE_TAG); if (dialogState != null) { mDialog.onRestoreInstanceState(dialogState); } } } @Override public void onStart() { super.onStart(); if (mDialog != null) { mViewDestroyed = false; mDialog.show(); } }