Подтвердить что ты не робот

DialogFragment и onDismiss

Я использую DialogFragment, который я показываю так из Activity:

DialogFragmentImage dialog = DialogFragmentImage.newInstance(createBitmap());
dialog.onDismiss(dialog);.onDismiss(this);          
dialog.show(getFragmentManager(), "DialogFragmentImage");

Я хотел бы проверить, когда DialogFragment был отклонен (например, когда была нажата кнопка "Назад"), но в моей Activity. Как я могу это сделать? Как я могу "сказать" моей activity что DialogFragment был отклонен?

4b9b3361

Ответ 1

Сделайте свою реализацию OnDismissListener

public final class YourActivity extends Activity implements DialogInterface.OnDismissListener {

    @Override
    public void onDismiss(final DialogInterface dialog) {
        //Fragment dialog had been dismissed
    }

}

DialogFragment уже реализует OnDismissListener, просто переопределяет метод и вызывает 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);
        }
    }

}

Если вы начинаете диалог с фрагмента с помощью менеджера childFragment (API >= 17), вы можете использовать getParentFragment для разговора с onDismissListener на родительском фрагменте.:

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);
        } 
    }

}

Ответ 2

Вот мой ответ. Это немного поздно, но это может помочь кому-то пройти мимо.

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
                    }
                });

Нам нужно позвонить

fm.executePendingTransactions(); 

Чтобы убедиться, что работа FragmentTransaction выполнена. В противном случае NullPointerException может возникать при вызове setOnDismissListener().

Извините, если есть какая-либо ошибка. Надеюсь на эту помощь.

Ответ 3

Альтернативный ответ, если у вас нет доступа к методу onDismiss активности.

//DIALOGFRAGMENT
//Create interface in your DialogFragment (or a new file)
public interface OnDismissListener {
   void onDismiss(MyDialogFragment myDialogFragment);
}
//create Pointer and setter to it
private OnDismissListener onDismissListener;
public void setDissmissListener(DissmissListener dissmissListener) {
   this.dissmissListener = dissmissListener;
}
//Call it on the dialogFragment onDissmiss
@Override
public void onDismiss(DialogInterface dialog) {
   super.onDismiss(dialog);

   if (onDismissListener != null) {
      onDismissListener.onDismiss(this);
   }
}

//OTHER CLASS, start fragment where you want
MyDialogFragment df = new MyDialogFragment();
df.setOnDismissListener(new MyDialogFragment.OnDismissListener() {
   @Override
   public void onDismiss(MyDialogFragment myDialogFragment) {
      //Call when MyDialogFragment close
   }
});
df.show(activity.getFragmentManager(), "myDialogFragment");

изменить:, если системе необходимо воссоздать DialogFragment: вы можете найти его с помощью

MyDialogFragment myDialogFragment = getFragmentManager().findFragmentByTag("MyDialogFragment"); 
if(myDialogFragment != null) { 
   myDialogFragment.setOnDismissListener(...); 
}

Ответ 4

Это старая проблема, но я не нашел решения, которым я доволен. Мне не нравится передавать никаких прослушивателей в свой диалог DialogFragment или устанавливать TargetFragment, потому что это может нарушить изменение ориентации. Что Вы думаете об этом?

        MyDialog d = new MyDialog();
        d.show(fragmentManager, "tag");
        fragmentManager.registerFragmentLifecycleCallbacks(new FragmentManager.FragmentLifecycleCallbacks() {
            @Override
            public void onFragmentViewDestroyed(FragmentManager fm, Fragment f) {
                super.onFragmentViewDestroyed(fm, f);
                //do sth      
        fragmentManager.unregisterFragmentLifecycleCallbacks(this);
                }
            }, false);

Ответ 5

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;
    }
}

и в вызове

OpcoesProdutoDialogo opcProduto = OpcoesProdutoDialogo.criar(itemPedido);
        opcProduto.show(getFragmentManager(), "opc_produto_editar");
        opcProduto.setOnDismissListener(d->{
            adapterItens.notifyItemChanged(posicao);
        });

Ответ 6

Если вам не нравится решение @yaroslav-mytkalyk, в котором фрагмент должен приводить фрагмент активность/родительский фрагмент, вот еще один:

Здесь идея:

  1. Выставьте слушателя в вашем фрагменте, DialogFragmentImage.
  2. Реализуйте слушателя в своей деятельности и передайте его фрагменту при его создании. Убедитесь, что вы также используете тег, чтобы найти фрагмент позже (см. Ниже).
  3. В onStop() удалите прослушиватель, чтобы не onStop() активность, если она уничтожена. Это произойдет при повороте экрана, поскольку действие будет воссоздано.
  4. В onResume() проверьте, существует ли фрагмент, и если да, повторно добавьте прослушиватель.

Выставьте слушателя из вашего фрагмента:

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.
    */
}

И вот как должна выглядеть ваша деятельность:

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 re-created.
        @Nullable MyFragment myFragment =  (MyFragment) getSupportFragmentManager().findFragmentByTag(MY_FRAGMENT_TAG);
        if (myFragment != null) {
            myFragment.setOnDismissListener(null);
        }

        super.onStop();
    }
}

Ответ 7

Вы можете создать подкласс DialogFragment и предоставить свой собственный слушатель, который будет вызываться и в onCancel.

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

Для тех, кто не знаком с Kotlin, это всего лишь анонимный интерфейс, который сохраняет стандартный интерфейс в Java. Используйте поле и сеттер в Java.

И тогда в onCancel

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

Повеселись!