官方推薦的Dialog——DialogFragment

簡介

官方推薦使用的Dialog類型,繼承自Fragment,通過FragmentManager管理對話彈框。由於繼承自Fragment,使用dialog時完全可以將其看作Fragment。
使用DialogFragment需要實現onCreateView()、onCreateDialog()其中之一
onCreateView即將完全自定義一個dialog。
onCreateDialog即重用Dialog樣式,僅用此管理dialog。

好處:
1. 旋轉屏幕、按下後退鍵時 等情況可以更好的管理其聲明週期。
2. 提供方法將Dialog作爲內嵌的組件進行重用

實現
就將其完全當作一個Fragment來使用就OK了,這裏就不貼代碼了。。。

注意點

1.去掉dialog的title

在onCreateView方法中添加getDialog().requestWindowFeature(Window.FEATURE_NO_TITLE);

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        getDialog().requestWindowFeature(Window.FEATURE_NO_TITLE);
        View inflate = inflater.inflate(R.layout.dialog_picture_verfy, container);
        ButterKnife.inject(this, inflate);
        return inflate;
    }

2.Activity傳參到Dialog

使用Fragment的傳參方式

    public static PictureVerfyDialog newInstance(FaFaIMMessageModel fafaModel) {
        Bundle args = new Bundle();
        args.putSerializable(PARAM_FAFA_MESSAGE, fafaModel);
        PictureVerfyDialog fragment = new PictureVerfyDialog();
        fragment.setArguments(args);
        return fragment;
    }

3.物理返回鍵不消失

onCreate()方法中調用:

this.setCancelable(false);

onCreateDialog方式:

點擊外部不消失的方法:getDialog.setCanceledOnTouchOutside(false);

對於點擊返回鍵不消失,需要監聽OnKeyListener:

getDialog().setOnKeyListener(new DialogInterface.OnKeyListener() {
            @Override
            public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
                if (keyCode == KeyEvent.KEYCODE_BACK) {
                    return true;
                }
                return false;
            }
        });

4.傳遞數據給Activity

類似fragment,通過Interface外拋的方式傳遞數據

    /**
     * 1. 創建監聽接口
     *
     * @author fengzhen
     * @version v5.2.4, 2017/6/22 18:36
     */
    public interface OnDismissListener {
        void onDismiss();
    }

    // 2. 內部屬性
    private OnDismissListener mOnDismissListener;

    /**
     * 3. 設置監聽接口, activity中調用此方法進行設置
     *
     * @author fengzhen
     * @version v5.2.4, 2017/6/22 18:38
     */
    public void setmOnDismissListener(OnDismissListener mOnDismissListener) {
        this.mOnDismissListener = mOnDismissListener;
    }

    // 4. 具體的使用,調用activity中的接口的具體實現方法
    public void onDismiss() {
        if (mOnDismissListener != null){
            mOnDismissListener.onDismiss();
        }
    }

5.拋出異常:IllegalStateException

調用show()方法拋出此異常
IllegalStateException: Can not perform this action after onSaveInstanceState

解決方式:
官方提供了方法:

    /** {@hide} */
    public void showAllowingStateLoss(FragmentManager manager, String tag) {
        mDismissed = false;
        mShownByMe = true;
        FragmentTransaction ft = manager.beginTransaction();
        ft.add(this, tag);
        ft.commitAllowingStateLoss();
    }

但是很心機的hide了,這裏通過反射的方式,強行執行這個方法的內容。

    /**
     * 使用反射重寫showAllowingStateLoss()方法
     * 解決調用show()方法異常
     *
     * @author fengzhen
     * @version v5.2.4, 2017/7/2 17:29
     */
    public void showAllowingStateLoss(FragmentManager manager, String tag) {
        try {
            Field mDismissed = DialogFragment.class.getDeclaredField("mDismissed");
            mDismissed.setAccessible(true);
            mDismissed.set(this,false);
            Field mShownByMe = DialogFragment.class.getDeclaredField("mShownByMe");
            mShownByMe.setAccessible(true);
            mShownByMe.set(this,true);
        } catch (Exception e) {
            e.printStackTrace();
        }
        FragmentTransaction ft = manager.beginTransaction();
        ft.add(this, tag);
        ft.commitAllowingStateLoss();
    }

注意不能直接把@hide的方法反射出來調用,所以下面的方法拋出異常 NosuchMethodException:

    public void showAllowingStateLoss(FragmentManager manager, String tag) {
        try {
            Method showAllowingStateLoss = DialogFragment.class.getDeclaredMethod("showAllowingStateLoss", FragmentManager.class, String.class);
            showAllowingStateLoss.setAccessible(true);
            showAllowingStateLoss.invoke(this, manager, tag);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

補充

1. 反射中:getDeclaredMethod()、getMethod區別

getDeclaredMethod():類自身聲明的所有方法
getMethod():獲取的是public方法

2.反射中:private的屬性

賦值之前setAccessible(true),設定爲可以修改。
發佈了82 篇原創文章 · 獲贊 69 · 訪問量 14萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章