Androidは袖をまくり、自分でDialogFragmentを封入する

19813 ワード

転載は出典作者:developerHaoz Github住所:developerHaoz
本文の主な内容
  • DialogFragmentとは何ですか
  • 共通のCommonDialogFragment
  • を作成
  • 各種のDialogFragment
  • を実現する
    本文を書く前に、まず効果を見せましょう.
    一、DialogFragmentとは何か
    DialogFragmentはAndroid 3.0で導入され、Activityのコンテンツの上に静的なダイアログボックスを表示するための特殊なFragmentです.たとえば、警告ボックス、入力ボックス、確認ボックスなどです.
    1、DialogFragmentの長所
    実はAndroidに表示されるダイアログボックスには、DialogFragmentとDialogの2種類があります.DialogFragmentが発生する前に、ダイアログボックスを作成するにはDialogを採用していました.また、コードの作成の観点から、Dialogの使用はもっと簡単でしたが、GoogleはできるだけDialogFragmentを使用することをお勧めしています.変な感じがしますが、原因も簡単です.DialogFragmentはDialogにはない非常に良い特性を持っています.DialogFragment自体はFragmentのサブクラスで、Fragmentとほぼ同じライフサイクルを持っています.DialogFragmentを使用してダイアログボックスを管理します.画面を回転したり、後退ボタンを押したりすると、ライフサイクルをよりよく管理できます.携帯電話の構成が変化してActivityが再作成される必要がある場合、たとえば画面を回転すると、DialogFragmentベースのダイアログボックスはFragmentManagerによって自動的に再構築されますが、Dialogベースのダイアログボックスにはそのような機能はありません.
    2、DialogFragmentの使用
    DialogFragmentを使用するには、少なくともonCreateView()またはonCreateDialog()メソッドを実装する必要があります.onCreateView()は、カスタムxmlレイアウトファイルを使用してDialogを表示します.onCreateDialog()は、AlertDialogまたはDialogを使用して私たちが望んでいるDialogを作成します.この文章は主にDialogFragmentのパッケージを説明しているため、DialogFragmentの具体的な使用については、Android公式推奨:DialogFragment作成ダイアログボックス
    二、共通のCommonDialogFragmentの作成
    このクラスはDialogFragmentのサブクラスであり,DialogFragmentをカプセル化し,外部からのAlertDialogに依存して構築するとともに,DialogFragmentにおけるAlertDialogが外部キャンセルを設定できないという問題も扱う.
    public class CommonDialogFragment extends DialogFragment {
    
        /**
         *           
         */
        private OnDialogCancelListener mCancelListener;
    
        /**
         *          dialog
         */
        private OnCallDialog mOnCallDialog;
    
        public interface OnDialogCancelListener {
            void onCancel();
        }
    
        public interface OnCallDialog {
            Dialog getDialog(Context context);
        }
    
        public static CommonDialogFragment newInstance(OnCallDialog call, boolean cancelable) {
            return newInstance(call, cancelable, null);
        }
    
        public static CommonDialogFragment newInstance(OnCallDialog call, boolean cancelable, OnDialogCancelListener cancelListener) {
            CommonDialogFragment instance = new CommonDialogFragment();
            instance.setCancelable(cancelable);
            instance.mCancelListener = cancelListener;
            instance.mOnCallDialog = call;
            return instance;
        }
    
        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            if (null == mOnCallDialog) {
                super.onCreateDialog(savedInstanceState);
            }
            return mOnCallDialog.getDialog(getActivity());
        }
    
        @Override
        public void onStart() {
            super.onStart();
            Dialog dialog = getDialog();
            if (dialog != null) {
                // 5.0              ,  5.0                    
                if(Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {
                    //       dialog     
                    if(dialog instanceof ProgressDialog || dialog instanceof DatePickerDialog) {
                        getDialog().getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
                    }
                }
                Window window = getDialog().getWindow();
                WindowManager.LayoutParams windowParams = window.getAttributes();
                windowParams.dimAmount = 0.0f;
                window.setAttributes(windowParams);
            }
        }
    
        @Override
        public void onCancel(DialogInterface dialog) {
            super.onCancel(dialog);
            if (mCancelListener != null) {
                mCancelListener.onCancel();
            }
        }
    
    }

    このクラスを見ることができるコード量も少なく、まず2つのインタフェースOnDialogCancelListener,OnCallDialogを定義し、前者はポップアップウィンドウがキャンセルされたかどうかを傍受するために使用され、後者は表示したいDialogをコールバックさせることができ、onCreateDialog()ではmOnCallDialog.getDialog(getActivity);を返し、Dialogに入力すると、ここにコールバックして、onCreateDialog()に私たちが伝えたDialogに戻って、 のよく分からない友达に対して、この文章の経典の例を見てjavaコールバックのメカニズムを徹底的に理解させることができます.
    続いてonStart()では、5.0以下のバージョンでProgressDialogとDatePickerDialogに白い枠が表示されるため、ユーザー体験が非常に悪いので、ここで対応する処理を行います.
    最後に、コンストラクション関数newInstance(OnCallDialog call, boolean cancelable, OnDialogCancelListener cancelListener)をカプセル化します.このCommonDialogFragmentを使用する場合は、まずOnCallDialogをnewして、表示したいDialogを転送します.cancelableは、ダイアログボックスがキャンセルされるかどうかを設定するために使用されます.onCancel()にこのようなコードがあることがわかります.
    if(mCancelListener != null){
      mCancelListener.onCancel();
    }

    これがコンストラクション関数にOnCancelListenerを入力する理由です.キャンセルダイアログの処理をしたい場合は、コンストラクション関数にOnCancelListenerを入力してonCancel()メソッドを実装すればいいのです.
    三、各種のDialogFragmentを実現する
    前にすべてのDialogFragmentのベースクラスとしてCommonFragmentを作成した以上、次はもちろん様々なタイプのDialogFragmentを実装しなければなりません.私の考えはDialogFragmentHelperを実装プロンプトボックスのヘルプクラスとして作成し、コードをカプセル化して、使用するときはAlertDialogとのインタラクションに注目するだけです.HelperはDialogFragmentで表示するのを助けてくれます.これにより、アプリケーション全体のDialogスタイルを統一することができ、さまざまなダイアログボックスを実現することができます.
    DialogFragmentHelperを実現する前に2つ事前にやっておきます
    1、stylesファイルで私たちのダイアログボックスのスタイルスタイルスタイルを定義する
    <style name="Base_AlertDialog" parent="Base.Theme.AppCompat.Light.Dialog">
    
            
            <item name="windowMinWidthMinor">90%item>
    
            
            <item name="android:windowNoTitle">trueitem>
    
            
            
    
            
            <item name="android:topDark">@color/app_main_color_deepitem>
    
            
    
            
            
            
    
            
            
    
            
            <item name="colorAccent">@color/app_main_coloritem>
        style>

    私はすでに詳しい注釈を打ったので、理解しやすいと信じています.
    2、DialogFragmentHelperと論理層の間でデータ傍受を行うためのインタフェースを書く
    public interface IDialogResultListener {
        void onDataResult(T result);
    }

    準備が終わったら、DialogFragmentHelperを始めましょう.紙面が限られているので、私は代表的にその中のいくつかの効果を選んだだけです.具体的なコードは、DialogFragmentDemosを参考にすることができます.
    public class DialogFragmentHelper {
    
        private static final String TAG_HEAD = DialogFragmentHelper.class.getSimpleName();
    
        /**
         *        
         */
        private static final int PROGRESS_THEME = R.style.Base_AlertDialog;
        private static final String PROGRESS_TAG = TAG_HEAD + ":progress";
    
    
        public static CommonDialogFragment showProgress(FragmentManager fragmentManager, String message){
            return showProgress(fragmentManager, message, true, null);
        }
    
        public static CommonDialogFragment showProgress(FragmentManager fragmentManager, String message, boolean cancelable){
            return showProgress(fragmentManager, message, cancelable, null);
        }
    
        public static CommonDialogFragment showProgress(FragmentManager fragmentManager, final String message, boolean cancelable
                , CommonDialogFragment.OnDialogCancelListener cancelListener){
    
            CommonDialogFragment dialogFragment = CommonDialogFragment.newInstance(new CommonDialogFragment.OnCallDialog() {
                @Override
                public Dialog getDialog(Context context) {
                    ProgressDialog progressDialog = new ProgressDialog(context, PROGRESS_THEME);
                    progressDialog.setMessage(message);
                    return progressDialog;
                }
            }, cancelable, cancelListener);
            dialogFragment.show(fragmentManager, PROGRESS_TAG);
            return dialogFragment;
        }
    
        /**
         *         
         */
        private static final int INSERT_THEME = R.style.Base_AlertDialog;
        private static final String INSERT_TAG  = TAG_HEAD + ":insert";
    
        public static void showInsertDialog(FragmentManager manager, final String title, final IDialogResultListener resultListener, final boolean cancelable){
    
            CommonDialogFragment dialogFragment = CommonDialogFragment.newInstance(new CommonDialogFragment.OnCallDialog() {
                @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
                @Override
                public Dialog getDialog(Context context) {
                    final EditText editText = new EditText(context);
                    editText.setBackground(null);
                    editText.setPadding(60, 40, 0, 0);
                    AlertDialog.Builder builder = new AlertDialog.Builder(context, INSERT_THEME);
                    builder.setTitle(title);
                    builder.setView(editText);
                    builder.setPositiveButton(DIALOG_POSITIVE, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            if(resultListener != null){
                                resultListener.onDataResult(editText.getText().toString());
                            }
                        }
                    });
                    builder.setNegativeButton(DIALOG_NEGATIVE, null);
                    return builder.create();
    
                }
            }, cancelable, null);
            dialogFragment.show(manager, INSERT_TAG);
        }
    
    }

    私たちがCommonFragmentをカプセル化したため、これらの効果の実現はかなり簡単になったのではないでしょうか.これがカプセル化が私たちにもたらした便利さとメリットです. を例に挙げて、私たちがどのように実現したかを見てみましょう.
        public static CommonDialogFragment showProgress(FragmentManager fragmentManager, final String message, boolean cancelable
                , CommonDialogFragment.OnDialogCancelListener cancelListener){
    
            CommonDialogFragment dialogFragment = CommonDialogFragment.newInstance(new CommonDialogFragment.OnCallDialog() {
                @Override
                public Dialog getDialog(Context context) {
                    ProgressDialog progressDialog = new ProgressDialog(context, PROGRESS_THEME);
                    progressDialog.setMessage(message);
                    return progressDialog;
                }
            }, cancelable, cancelListener);
            dialogFragment.show(fragmentManager, PROGRESS_TAG);
            return dialogFragment;
        }

    まずCommonDialogFragmentのコンストラクション関数を呼び出し、ProgressDialogを転送し、cancelableとcancelListenerを順次転送し、最後にshow()関数を呼び出し、DialogFragmentを表示します.コンストラクション関数のリロードを使用すると、最も簡単なコンストラクション関数は2つのパラメータだけを転送すればよいことがわかります.かなり簡潔なのではないでしょうか.
    DialogFragmentと論理層の間でデータ傍受を行うためにIDialogResultListenerを作成したことを忘れていないでしょう.様々なタイプのデータを伝えるために、ここでは を使って処理しています. を例に、どのように使うかを見てみましょう.
        public static void showInsertDialog(FragmentManager manager, final String title, final IDialogResultListener resultListener, final boolean cancelable){
    
            CommonDialogFragment dialogFragment = CommonDialogFragment.newInstance(new CommonDialogFragment.OnCallDialog() {
    
                @Override
                public Dialog getDialog(Context context) {
    
                 // ...          
                    AlertDialog.Builder builder = new AlertDialog.Builder(context, INSERT_THEME);
                    builder.setPositiveButton(DIALOG_POSITIVE, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            if(resultListener != null){
                                resultListener.onDataResult(editText.getText().toString());
                            }
                        }
                    });
                    builder.setNegativeButton(DIALOG_NEGATIVE, null);
                    return builder.create();
    
                }
            }, cancelable, null);
            dialogFragment.show(manager, INSERT_TAG);
        }
    showInsertDialog()メソッドにIDialogResultListener resultListenerが入力されていることがわかります.入力されたコンテンツを処理したい場合は、外部で呼び出されたときにnew IDialogResultListenerが送信され、onDataResult()メソッドが実装されます.
    以上が全文の内容で、具体的なコードと例は私はすべてGithubを置いて、必要な友达がDialogFragmentDemosを见に行くことができて、もしあなたに役に立つと思ったら、starを赏しましょう!