DialogFragment и onDismiss
Я использую DialogFragment
, который я показываю так из Activity
:
DialogFragmentImage dialog = DialogFragmentImage.newInstance(createBitmap());
dialog.onDismiss(dialog);.onDismiss(this);
dialog.show(getFragmentManager(), "DialogFragmentImage");
Я хотел бы проверить, когда DialogFragment
был отклонен (например, когда была нажата кнопка "Назад"), но в моей Activity
. Как я могу это сделать? Как я могу "сказать" моей activity
что DialogFragment
был отклонен?
Ответы
Ответ 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, в котором фрагмент должен приводить фрагмент активность/родительский фрагмент, вот еще один:
Здесь идея:
- Выставьте слушателя в вашем фрагменте,
DialogFragmentImage
. - Реализуйте слушателя в своей деятельности и передайте его фрагменту при его создании. Убедитесь, что вы также используете тег, чтобы найти фрагмент позже (см. Ниже).
- В
onStop()
удалите прослушиватель, чтобы не onStop()
активность, если она уничтожена. Это произойдет при повороте экрана, поскольку действие будет воссоздано. - В
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()
}
Повеселись!