DialogFragment实践与原理

最近一直在看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原理

Fragment本质上是Android使用Handler对View的异步动态加载管理;DialogFragment是用Fragment对dialog展示进行管理的

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弹出Dialog
public 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();
    }
}











评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值