Android编程之DialogFragment源码详解(二)

接上篇,继续:


然后就是setShowsDialog(boolean showsDialog)方法。官方文档是这样解释的:控制DialogFragment是否是一个dislog,如果设置为false,则没有dialog被创建出来,你可以把它当做一个普通的Fragemnt使用。

开头提到了,mShowsDialog默认为true,所以如果你把DialogFragment确实作为一个Dialog使用,那大可不必调这个方法。当我看到OnCreate的方法时,就更加确定。(官方文档上说了一种情况,需要手动调用它,这种情况及其少见,有兴趣的可以自行去研究)。

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public void setShowsDialog(boolean showsDialog) {  
  2.     mShowsDialog = showsDialog;  
  3. }  

来看onCreate方法:
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. @Override  
  2. public void onCreate(Bundle savedInstanceState) {  
  3.     super.onCreate(savedInstanceState);  
  4.   
  5.     mShowsDialog = mContainerId == 0;  
  6.   
  7.     if (savedInstanceState != null) {  
  8.         mStyle = savedInstanceState.getInt(SAVED_STYLE, STYLE_NORMAL);  
  9.         mTheme = savedInstanceState.getInt(SAVED_THEME, 0);  
  10.         mCancelable = savedInstanceState.getBoolean(SAVED_CANCELABLE, true);  
  11.         mShowsDialog = savedInstanceState.getBoolean(SAVED_SHOWS_DIALOG, mShowsDialog);  
  12.         mBackStackId = savedInstanceState.getInt(SAVED_BACK_STACK_ID, -1);  
  13.     }  
  14.       
  15. }  
mShowsDialog = mContainerId == 0;

没错,默认情况下,mContainerId就是0,所以mShowsDialog自然就是true;而当你在把它当成Fragment使用时,会为其指定xml布局中位置,所以,mContainerId也会不为0,所以mShowsDialog自然就是false。


然后是LayoutInflater getLayoutInflater(Bundle savedInstanceState),这个方法被hide了,所以外部是调不到的。

简单说一下这个getLayoutInflater方法,它的调用点是在onCreateView的时候,从先后顺序来说getLayoutInflater在onCreateView之前。

摘自FragmentManager:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. f.mView = f.onCreateView(f.getLayoutInflater(f.mSavedFragmentState),null, f.mSavedFragmentState);  

getLayoutInflater方法如下:
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /** @hide */  
  2. @Override  
  3. public LayoutInflater getLayoutInflater(Bundle savedInstanceState) {  
  4.     if (!mShowsDialog) {  
  5.         return super.getLayoutInflater(savedInstanceState);  
  6.     }  
  7.   
  8.     mDialog = onCreateDialog(savedInstanceState);  
  9.     switch (mStyle) {  
  10.         case STYLE_NO_INPUT:  
  11.             mDialog.getWindow().addFlags(  
  12.                     WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |  
  13.                     WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);  
  14.             // fall through...  
  15.         case STYLE_NO_FRAME:  
  16.         case STYLE_NO_TITLE:  
  17.             mDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);  
  18.     }  
  19.     if (mDialog != null) {  
  20.         return (LayoutInflater) mDialog.getContext().getSystemService(  
  21.                 Context.LAYOUT_INFLATER_SERVICE);  
  22.     }  
  23.     return (LayoutInflater) mActivity.getSystemService(  
  24.             Context.LAYOUT_INFLATER_SERVICE);  
  25. }  

如果不是Dialog,则调用Fragment自身的方法;否则,就先创建一个dialog,然后,根据之前设置的style,对dialog赋值。所以, setStyle这个方法调用,一定要在onCreateView之前。 一般来讲,都会放到onCreate中调用。

STYLE_NO_FRAME和STYLE_NO_TITLE都调用了mDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);

那它们两个参数有什么不同呢,答案就在开头setStyle中,STYLE_NO_FRAME会再没有theme的情况下,设置theme为android.R.style.Theme_Panel。


然后就是onCreateDialog方法,你可以重写这个方法,创建一个自己定义好的dialog。默认情况下,会自己创建一个Dialog。

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public Dialog onCreateDialog(Bundle savedInstanceState) {  
  2.     return new Dialog(getActivity(), getTheme());  
  3. }  

再说一个onDismiss方法,没错,它是DialogInterface.OnDismissListener中的方法,DialogFragment实现了它。所以,在dialog不显示后,会回调这个方法,然后再去调用自己的dismissInternal方法:
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public void onDismiss(DialogInterface dialog) {  
  2.     if (!mViewDestroyed) {  
  3.         dismissInternal(true);  
  4.     }  
  5. }  

那么,dialog什么时候显示出来?是在OnStart的时候:
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. @Override  
  2. public void onStart() {  
  3.     super.onStart();  
  4.     if (mDialog != null) {  
  5.         mViewDestroyed = false;  
  6.         mDialog.show();  
  7.     }  
  8. }  

而与其对应的生命周期方法onStop()时,则是将其先隐藏了。
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. @Override  
  2. public void onStop() {  
  3.     super.onStop();  
  4.     if (mDialog != null) {  
  5.         mDialog.hide();  
  6.     }  
  7. }  

最后就是onDestroyView方法,它会将dialog销毁。
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. @Override  
  2. public void onDestroyView() {  
  3.     super.onDestroyView();  
  4.     if (mDialog != null) {  
  5.         mViewDestroyed = true;  
  6.         mDialog.dismiss();  
  7.         mDialog = null;  
  8.     }  
  9. }  


好了,以上就是DialogFragment源码部分。


小结:

1、DialogFragment本质上说就是Fragment,只是其内部还有一个dialog而已。你既可以当它是Dialog使用,也可以把它作为Fragment使用。

2、setStyle中,style的参数是不可以相互一起使用的,只能用一个,如果还不满足你使用,可以通过设置theme来满足。

3、setStyle的调用点,要放在onCreateView前,否则,设置的style和theme将不起作用!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值