DialogFragment and onDismiss

前端 未结 8 1836
迷失自我
迷失自我 2020-11-27 16:14

I am using a DialogFragment, which I am showing like this from an Activity:

DialogFragmentImage dialog = DialogFragmentImage.newIns         


        
相关标签:
8条回答
  • 2020-11-27 16:19

    If you don't like the solution of @yaroslav-mytkalyk, in which the fragment needs to cast the activity / parent fragment, here's another one:

    Here's the idea:

    1. Expose a listener in your fragment, DialogFragmentImage.
    2. Implement the listener in your activity and pass it to the fragment when creating it. Make sure to use a tag as well in order to be able to find the fragment later (read below).
    3. In onStop(), remove the listener in order not to leak the activity if it's destroyed. This will happen when the screen is rotated, as the activity will be re-created.
    4. In onResume(), check if the fragment exists and if yes, re-add the listener.

    Expose a listener from your fragment:

    class MyFragment extends DialogFragment {
    
        public interface OnDismissListener {
            void dismissed();
        }
    
        @Nullable
        private OnDismissListener onDismissListener;
    
        public void setOnDismissListener(@Nullable OnDismissListener onDismissListener) {
            this.onDismissListener = onDismissListener;
        }
    
        /*
        If you are calling dismiss() or dismissAllowingStateLoss() manually,
        don't forget to call:
        if (onDismissListener != null) {
            onDismissListener.dismissed();
        }
    
        Otherwise, override them and call it there.
        */
    }
    

    And this is how your activity should look like:

    class MyActivity extends AppCompatActivity {
    
        private static final String MY_FRAGMENT_TAG = "my_fragment";
    
        private MyFragment.OnDismissListener myFragmentListener = () -> {
    
            // ...
        };
    
        /**
         * Shows the fragment. Note that:
         * 1. We pass a tag to `show()`.
         * 2. We set the listener on the fragment.
         */
        private void showFragment() {
    
            MyFragment fragment = new MyFragment();
            fragment.show(getSupportFragmentManager(), MY_FRAGMENT_TAG);
            fragment.setOnDismissListener(myFragmentListener);
        }
    
        @Override
        protected void onStart() {
    
            super.onStart();
    
            // Restore the listener that we may have removed in `onStop()`.
            @Nullable MyFragment myFragment =  (MyFragment) getSupportFragmentManager().findFragmentByTag(MY_FRAGMENT_TAG);
            if (myFragment != null) {
                myFragment.setOnDismissListener(myFragmentListener);
            }
        }
    
        @Override
        protected void onStop() {
    
            // If the fragment is currently shown, remove the listener so that the activity is not leaked when e.g. the screen is rotated and it's re-created.
            @Nullable MyFragment myFragment =  (MyFragment) getSupportFragmentManager().findFragmentByTag(MY_FRAGMENT_TAG);
            if (myFragment != null) {
                myFragment.setOnDismissListener(null);
            }
    
            super.onStop();
        }
    }
    
    0 讨论(0)
  • 2020-11-27 16:26

    Make your Activity implement OnDismissListener

    public final class YourActivity extends Activity implements DialogInterface.OnDismissListener {
    
        @Override
        public void onDismiss(final DialogInterface dialog) {
            //Fragment dialog had been dismissed
        }
    
    }
    

    DialogFragment already implements OnDismissListener, just override the method and call the Activity.

    public final class DialogFragmentImage extends DialogFragment {
    
        ///blah blah
    
        @Override
        public void onDismiss(final DialogInterface dialog) {
            super.onDismiss(dialog);
            final Activity activity = getActivity();
            if (activity instanceof DialogInterface.OnDismissListener) {
                ((DialogInterface.OnDismissListener) activity).onDismiss(dialog);
            }
        }
    
    }
    

    If you're starting the dialog from a fragment using the childFragment manager (API>=17), you can use getParentFragment to talk to the onDismissListener on the parent fragment.:

    public final class DialogFragmentImage extends DialogFragment {
    
        ///blah blah
    
        @Override
        public void onDismiss(final DialogInterface dialog) {
            super.onDismiss(dialog);
            Fragment parentFragment = getParentFragment();
            if (parentFragment instanceof DialogInterface.OnDismissListener) {
                ((DialogInterface.OnDismissListener) parentFragment).onDismiss(dialog);
            } 
        }
    
    }
    
    0 讨论(0)
  • 2020-11-27 16:26

    You can subclass DialogFragment and provide your own listener that is going to be called and in onCancel.

    var onDismissListener: (() -> Unit)? = null
    

    For the ones not familiar with Kotlin this is just an anonymous interface that saves boilerplate iterface in Java. Use a field and a setter in Java.

    And then in onCancel

        override fun onCancel(dialog: DialogInterface?) {
        super.onCancel(dialog)
        onDismissListener?.invoke()
    }
    

    Have fun!

    0 讨论(0)
  • 2020-11-27 16:27

    Here is my answer. It's a bit late but it's maybe benefit someone passing by.

    FragmentManager fm = getFragmentManager();
    
    YourDialogFragment dialog = new YourDialogFragment();
    dialog.show(fm,"MyDialog");
    
    fm.executePendingTransactions();
    dialog.getDialog().setOnDismissListener(new DialogInterface.OnDismissListener() {
                        @Override
                        public void onDismiss(DialogInterface dialogInterface) {
                           //do whatever you want when dialog is dismissed
                        }
                    });
    

    We need to call

    fm.executePendingTransactions(); 
    

    To make sure that FragmentTransaction work has been performed. Otherwise NullPointerException can occur when calling setOnDismissListener().

    Sorry if there is any mistake. Hope this help.

    0 讨论(0)
  • 2020-11-27 16:32
    public class OpcoesProdutoDialogo extends DialogFragment{
        private DialogInterface.OnDismissListener onDismissOuvinte;
    .
    .
    .
    
    @Override
        public void onDismiss(DialogInterface dialog) {
            super.onDismiss(dialog);
            if(onDismissOuvinte!=null)
                onDismissOuvinte.onDismiss(dialog);
        }
    
        public void setOnDismissListener(@Nullable DialogInterface.OnDismissListener listener) {
            this.onDismissOuvinte = listener;
        }
    }
    

    and in call

    OpcoesProdutoDialogo opcProduto = OpcoesProdutoDialogo.criar(itemPedido);
            opcProduto.show(getFragmentManager(), "opc_produto_editar");
            opcProduto.setOnDismissListener(d->{
                adapterItens.notifyItemChanged(posicao);
            });
    
    0 讨论(0)
  • 2020-11-27 16:40

    Care : all example aren't correct because your fragment should have a no-arg constructor !

    Working code with back gesture and close button in the fragment itself. I removed useless code stuff like getting arg in onCreate etc.

    Important : onDismiss is also call when orientation change so as a result you should check if the context is not null in your callback (or using other stuff).

    public class MyDialogFragment extends DialogFragment {
    
        public static String TAG = "MyFragment";
    
        public interface ConfirmDialogCompliant {
            void doOkConfirmClick();
        }
    
    
        public MyFragment(){
            super();
        }
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            // Inflate the layout for this fragment
            View rootView = inflater.inflate(R.layout.fragment_layout, container, false);
    
            ((ImageButton) rootView.findViewById(R.id.btn_close)).setOnClickListener(new View.OnClickListener() {
                public void onClick(View v) {
                    // close fragment
                    dismiss();
                }
            });
            return rootView;
        }
    
        @Override
        public void onDismiss(@NonNull DialogInterface dialog) {
            super.onDismiss(dialog);
            // notify
            if(caller != null)
               caller.doOkConfirmClick();
            }
        }
    
      public void setCallback(ConfirmDialogCompliant caller) {
        this.caller = caller;
      }
    
     public static MyDialogFragment newInstance(String id) {
        MyDialogFragment f = new MyDialogFragment();
    
        // Supply num input as an argument.
        Bundle args = new Bundle();
        args.putString("YOU_KEY", id);
        f.setArguments(args);
    
        return f;
    }
    

    }

    And now how to call it from parent.

    MyDialogFragment.ConfirmDialogCompliant callback = new MyDialogFragment.ConfirmDialogCompliant() {
    
                @Override
                public void doOkConfirmClick() {
                    // context can be null, avoid NPE
                    if(getContext() != null){
    
                    }
    
                }
    
            };
    
        MyDialogFragment fragment = MyDialogFragment.newInstance("item");
        fragment.setCallback(callback);
        fragment.show(ft, MyDialogFragment.TAG);
            new MyDialogFragment(callback, item);
    
        fragment.show(getActivity().getSupportFragmentManager(), MyDialogFragment.TAG);
    

    Additionnal source : https://developer.android.com/reference/android/app/DialogFragment

    0 讨论(0)
提交回复
热议问题