Android DialogFragment 和 onDismiss
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/23786033/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
DialogFragment and onDismiss
提问by deimos1988
I am using a DialogFragment
, which I am showing like this from an Activity
:
我正在使用 a DialogFragment
,我从 an 显示如下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
. How can I do that? How can I "tell" my activity
that the DialogFragment
has been dismissed?
我想检查何时DialogFragment
被解雇(例如,当按下后退按钮时),但在我的Activity
. 我怎样才能做到这一点?我如何“告诉”我activity
的DialogFragment
已被解雇?
回答by Yaroslav Mytkalyk
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);
}
}
}
回答by Boonya Kitpitak
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()
.
确保已执行 FragmentTransaction 工作。否则NullPointerException
在调用setOnDismissListener()
.
Sorry if there is any mistake. Hope this help.
如有错误,请见谅。希望这有帮助。
回答by Kaskasi
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. What do you think about this?
这是一个老问题,但我没有找到令我满意的解决方案。我不喜欢将任何侦听器传递给我的 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);
回答by Anthone
Alternative answer, if you don't have access to the methode onDismiss of activity.
替代答案,如果您无权访问 onDismiss of 活动的方法。
//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(...);
}
回答by d3roch4
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);
});
回答by Minas Mina
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:
这是想法:
- Expose a listener in your fragment,
DialogFragmentImage
. - 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).
- 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. - In
onResume()
, check if the fragment exists and if yes, re-add the listener.
- 在您的片段中公开一个侦听器,
DialogFragmentImage
. - 在您的活动中实现侦听器并在创建它时将其传递给片段。确保也使用标签,以便以后能够找到片段(阅读下文)。
- 在 中
onStop()
,删除侦听器,以免活动被破坏时泄漏。这将在屏幕旋转时发生,因为活动将被重新创建。 - 在 中
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:
这就是您的 Activity 的外观:
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();
}
}
回答by Zhar
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.
片段本身中带有后退手势和关闭按钮的工作代码。我删除了无用的代码内容,例如获取 argonCreate
等。
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
回答by Preslav Petkov
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. Use a field and a setter in Java.
对于那些不熟悉 Kotlin 的人来说,这只是一个匿名接口,可以在 Java 中保存样板 iterface。在 Java 中使用字段和设置器。
And then in onCancel
然后在 onCancel
override fun onCancel(dialog: DialogInterface?) {
super.onCancel(dialog)
onDismissListener?.invoke()
}
Have fun!
玩得开心!