spb 2018-10-13
目录介绍
好消息
1.最简单的使用方法
1.1 官方建议
1.2 最简单的使用方法
public class CustomDialogFragment extends DialogFragment { @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); //设置样式 setStyle(DialogFragment.STYLE_NO_TITLE, R.style.CenterDialog); } @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { return inflater.inflate(R.layout.view_fragment_dialog, container, false); } public static void showDialog(FragmentActivity activity){ CustomDialogFragment customDialogFragment = new CustomDialogFragment(); customDialogFragment.show(activity.getSupportFragmentManager(),"yc"); } } //然后一行代码调用 CustomDialogFragment.showDialog(this);
STYLE_NORMAL:会显示一个普通的dialog STYLE_NO_TITLE:不带标题的dialog STYLE_NO_FRAME:无框的dialog STYLE_NO_INPUT:无法输入内容的dialog,即不接收输入的焦点,而且触摸无效。
//第一种 //设置样式时,使用STYLE_NO_TITLE setStyle(DialogFragment.STYLE_NO_TITLE, R.style.CenterDialog); //第二种 @Override public void onActivityCreated(Bundle savedInstanceState) { Window window = getDialog().getWindow(); if(window!=null){ window.requestFeature(Window.FEATURE_NO_TITLE); } super.onActivityCreated(savedInstanceState); }
2.源码分析
2.1 DialogFragment继承Fragment
2.2 onCreate(@Nullable Bundle savedInstanceState)源码分析
@Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); mShowsDialog = mContainerId == 0; if (savedInstanceState != null) { mStyle = savedInstanceState.getInt(SAVED_STYLE, STYLE_NORMAL); mTheme = savedInstanceState.getInt(SAVED_THEME, 0); mCancelable = savedInstanceState.getBoolean(SAVED_CANCELABLE, true); mShowsDialog = savedInstanceState.getBoolean(SAVED_SHOWS_DIALOG, mShowsDialog); mBackStackId = savedInstanceState.getInt(SAVED_BACK_STACK_ID, -1); } }
2.3 setStyle(@DialogStyle int style, @StyleRes int theme)源码分析
public void setStyle(@DialogStyle int style, @StyleRes int theme) { mStyle = style; if (mStyle == STYLE_NO_FRAME || mStyle == STYLE_NO_INPUT) { mTheme = android.R.style.Theme_Panel; } if (theme != 0) { mTheme = theme; } }
2.4 onActivityCreated(Bundle savedInstanceState)源码分析
2.5 onCreateDialog(Bundle savedInstanceState)源码分析
@NonNull public Dialog onCreateDialog(Bundle savedInstanceState) { return new Dialog(getActivity(), getTheme()); }
2.6 重点分析弹窗展示和销毁源码
2.6.1 show方法
public void show(FragmentManager manager, String tag) { mDismissed = false; mShownByMe = true; FragmentTransaction ft = manager.beginTransaction(); ft.add(this, tag); ft.commit(); } public int show(FragmentTransaction transaction, String tag) { mDismissed = false; mShownByMe = true; transaction.add(this, tag); mViewDestroyed = false; mBackStackId = transaction.commit(); return mBackStackId; }
2.6.2 dismiss()销毁方法
2.6.3 dialog显示与隐藏
@Override public void onStart() { super.onStart(); if (mDialog != null) { mViewDestroyed = false; mDialog.show(); } } @Override public void onStop() { super.onStop(); if (mDialog != null) { mDialog.hide(); } } @Override public void onDestroyView() { super.onDestroyView(); if (mDialog != null) { // Set removed here because this dismissal is just to hide // the dialog -- we don't want this to cause the fragment to // actually be removed. mViewDestroyed = true; mDialog.dismiss(); mDialog = null; } }
3.经典总结
4.DialogFragment封装库介绍
项目地址:https://github.com/yangchong211/YCDialog
BottomDialogFragment.create(getSupportFragmentManager()) .setViewListener(new BottomDialogFragment.ViewListener() { @Override public void bindView(View v) { } }) .setLayoutRes(R.layout.dialog_bottom_layout_list) .setDimAmount(0.5f) .setTag("BottomDialog") .setCancelOutside(true) .setHeight(getScreenHeight() / 2) .show();
public class ADialog extends BaseDialogFragment { @Override protected boolean isCancel() { return false; } @Override public int getLayoutRes() { return 0; } @Override public void bindView(View v) { } }
5.常见问题总结
5.1 使用中show()方法遇到的IllegalStateException
lang.IllegalStateException: Can not perform this action after onSaveInstanceState at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1493)
//第一步: public FragmentManager getSupportFragmentManager() { return mFragments.getSupportFragmentManager(); } //第二步: public FragmentManager getSupportFragmentManager() { return mHost.getFragmentManagerImpl(); } //第三步: FragmentManagerImpl getFragmentManagerImpl() { return mFragmentManager; } //第四步:看beginTransaction()方法 @Override public FragmentTransaction beginTransaction() { return new BackStackRecord(this); } //第五步:看BackStackRecord类中看commit方法 @Override public int commit() { return commitInternal(false); } @Override public int commitAllowingStateLoss() { return commitInternal(true); } //第六步:可以看到这俩函数的区别就是commitInternal()方法中参数一个为true,一个为false int commitInternal(boolean allowStateLoss) { if (mCommitted) throw new IllegalStateException("commit already called"); if (FragmentManagerImpl.DEBUG) { Log.v(TAG, "Commit: " + this); LogWriter logw = new LogWriter(TAG); PrintWriter pw = new PrintWriter(logw); dump(" ", null, pw, null); pw.close(); } mCommitted = true; if (mAddToBackStack) { mIndex = mManager.allocBackStackIndex(this); } else { mIndex = -1; } mManager.enqueueAction(this, allowStateLoss); return mIndex; } //第七步:再追踪到enqueueAction(this,allowStateLoss) public void enqueueAction(OpGenerator action, boolean allowStateLoss) { if (!allowStateLoss) { checkStateLoss(); } synchronized (this) { if (mDestroyed || mHost == null) { throw new IllegalStateException("Activity has been destroyed"); } if (mPendingActions == null) { mPendingActions = new ArrayList<>(); } mPendingActions.add(action); scheduleCommit(); } } //第八步:checkStateLoss()方法,这里可以看到抛出的错误日志呢 private void checkStateLoss() { if (mStateSaved) { throw new IllegalStateException( "Can not perform this action after onSaveInstanceState"); } if (mNoTransactionsBecause != null) { throw new IllegalStateException( "Can not perform this action inside of " + mNoTransactionsBecause); } }