[英]DialogFragment and onDismiss
I am using a DialogFragment
, which I am showing like this from an Activity
:我正在使用
DialogFragment
,我从Activity
显示如下:
DialogFragmentImage dialog = DialogFragmentImage.newInstance(createBitmap());
dialog.onDismiss(dialog);.onDismiss(this);
dialog.show(getFragmentManager(), "DialogFragmentImage");
I would like to check when the DialogFragment
was dismissed (for example when the back button was pressed), but in my Activity
.我想检查
DialogFragment
被解除(例如按下后退按钮时),但在我的Activity
中。 How can I do that?我怎样才能做到这一点? How can I "tell" my
activity
that the DialogFragment
has been dismissed?如何“告诉”我的
activity
DialogFragment
已被解除?
Make your Activity implement OnDismissListener
让你的 Activity 实现
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. 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);
}
}
}
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.:如果您使用
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);
}
}
}
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.确保已执行 FragmentTransaction 工作。 Otherwise
NullPointerException
can occur when calling setOnDismissListener()
.否则调用
setOnDismissListener()
时可能会发生NullPointerException
。
Sorry if there is any mistake.如有错误请见谅。 Hope this help.
希望这有帮助。
This is an old issue but I found no solution I am happy with.这是一个老问题,但我没有找到满意的解决方案。 I don't like passing any Listeners to my DialogFragment or set a TargetFragment, because that may break on orientation change.
我不喜欢将任何侦听器传递给我的 DialogFragment 或设置 TargetFragment,因为这可能会在方向更改时中断。 What do you think about this?
你怎么看待这件事?
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);
Alternative answer, if you don't have access to the methode onDismiss of activity.替代答案,如果您无权访问活动的 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");
edit : if system need to recreate DialogFragment: you can find it with编辑:如果系统需要重新创建 DialogFragment:你可以找到它
MyDialogFragment myDialogFragment = getFragmentManager().findFragmentByTag("MyDialogFragment");
if(myDialogFragment != null) {
myDialogFragment.setOnDismissListener(...);
}
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);
});
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:如果您不喜欢@yaroslav-mytkalyk 的解决方案,其中片段需要强制转换活动/父片段,这里还有一个:
Here's the idea:这是想法:
DialogFragmentImage
.DialogFragmentImage
中公开一个侦听器。onStop()
, remove the listener in order not to leak the activity if it's destroyed.onStop()
中,移除监听器,以免活动被破坏时泄漏。 This will happen when the screen is rotated, as the activity will be re-created.onResume()
, check if the fragment exists and if yes, re-add the listener.onResume()
中,检查片段是否存在,如果存在,则重新添加侦听器。 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();
}
}
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.我删除了无用的代码内容,例如在
onCreate
中获取 arg 等。
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).重要提示:当方向改变时也会调用
onDismiss
,因此您应该检查回调中的上下文是否不为空(或使用其他内容)。
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附加来源: https ://developer.android.com/reference/android/app/DialogFragment
You can subclass DialogFragment and provide your own listener that is going to be called and in onCancel.您可以继承 DialogFragment 并提供您自己的侦听器,该侦听器将被调用并在 onCancel 中。
var onDismissListener: (() -> Unit)? = null
For the ones not familiar with Kotlin this is just an anonymous interface that saves boilerplate iterface in Java.对于不熟悉 Kotlin 的人来说,这只是一个匿名接口,可以在 Java 中保存样板 iterface。 Use a field and a setter in Java.
在 Java 中使用字段和设置器。
And then in onCancel然后在 onCancel
override fun onCancel(dialog: DialogInterface?) {
super.onCancel(dialog)
onDismissListener?.invoke()
}
Have fun!玩得开心!
Kotlin Answer科特林答案
private fun showMyCustomDialog() {
// Show.
MyCustomDialogFragment().show(fm, "MyCustomDialogFragment")
// Set pending transactions.
fm.executePendingTransactions()
// Listen dialog closing.
MyCustomDialogFragment().dialog?.setOnDismissListener {
// You can do you job when it closed.
}
}
Solution using kotlin and additional interface.使用 kotlin 和附加接口的解决方案。 (an example for a fragment will be shown here, but with a few changes it will work in an activity as well)
(此处将显示片段的示例,但进行一些更改后,它也可以在活动中工作)
First you need to create an interface (the set of parameters can be any):首先你需要创建一个接口(参数集可以是任意的):
interface DialogCloseListener {
fun handleDialogClose(dialog: DialogInterface)
}
Then implement this interface in the fragment that calls the DailogFragment:然后在调用 DailogFragment 的 Fragment 中实现这个接口:
class YourParentFragment: Fragment(), DialogCloseListener {
override fun handleDialogClose(dialog: DialogInterface) {
// do something
}
}
Now go to your DialogFragment.现在转到您的 DialogFragment。 Implement the onDismiss method.
实现 onDismiss 方法。 In it, check if the parent fragment implements your interface, call your method, passing the necessary parameters there:
在其中,检查父片段是否实现了您的接口,调用您的方法,并在那里传递必要的参数:
override fun onDismiss(dialog: DialogInterface) {
super.onDismiss(dialog)
if(parentFragment is DialogCloseListener){
(parentFragment as DialogCloseListener).handleDialogClose(dialog)
}
}
I think that this way is good because you can track a specific close event (by passing a certain parameter to the method), for example, canceling an order, and somehow handle it.我认为这种方式很好,因为您可以跟踪特定的关闭事件(通过将某个参数传递给方法),例如取消订单,并以某种方式处理它。
Try this尝试这个
dialog.setOnDismissListener { Log.e("example","example") }
Have Fun!玩得开心!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.