对话片段和解散

我使用的是 DialogFragment,我在 Activity上显示如下:

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

我想检查当 DialogFragment被解雇(例如当按下返回按钮) ,但在我的 Activity。我该怎么做?我如何“告诉”我的 activityDialogFragment已被解雇?

74385 次浏览

使您的活动实现 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);
}
}


}

另一种答案,如果你没有访问的方法上解散的活动。

//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(...);
}

这是我的回答。虽然有点晚了,但也许对路过的人有好处。

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

以确保已经执行了片段事务工作。否则,在调用 setOnDismissListener()时可能发生 NullPointerException

对不起,如果有任何错误。希望这个帮助。

这是一个老问题,但我没有找到令我满意的解决方案。我不喜欢传递任何监听器到我的对话框片段或设置一个目标片段,因为这可能会中断方向的变化。你觉得这个怎么样?

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

您可以子类化 DialogFragment 并提供您自己的侦听器,该侦听器将在 onCancel 中被调用。

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

对于那些不熟悉 Kotlin 的人来说,这只是一个匿名接口,可以在 Java 中保存样板文件。在 Java 中使用字段和 setter。

然后在 onCancel 中

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

玩得开心!

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

如果你不喜欢@yarrosv-mytkalyk 的解决方案,在这个解决方案中,片段需要强制执行活动/父片段,这里还有一个:

我的想法是这样的:

  1. 在片段 DialogFragmentImage中公开一个侦听器。
  2. 在活动中实现侦听器,并在创建时将其传递给片段。请确保也使用标记,以便能够在以后找到片段(请参阅下文)。
  3. 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's re-created.
@Nullable MyFragment myFragment =  (MyFragment) getSupportFragmentManager().findFragmentByTag(MY_FRAGMENT_TAG);
if (myFragment != null) {
myFragment.setOnDismissListener(null);
}


super.onStop();
}
}

注意: 所有示例都不正确,因为片段应该有一个 no-arg 构造函数!

在片段本身中使用后退手势和关闭按钮的工作代码。我删除了一些无用的代码,比如在 onCreate中获取 arg 等等。

重要提示: 当方向发生变化时,也会调用 onDismiss,从而导致 您应该检查回调中的上下文是否为 null(或使用其他东西)。

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

现在该如何从父母那里呼唤它。

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

附加来源: https://developer.android.com/reference/android/app/DialogFragment

Kotlin 答案

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

使用科特林和附加接口的解决方案。(这里将显示一个片段的示例,但只要做一些更改,它也可以在活动中工作)

首先,您需要创建一个接口(参数集可以是任意的) :

interface DialogCloseListener {
fun handleDialogClose(dialog: DialogInterface)
}

然后在调用 DailogFragment 的片段中实现这个接口:

class YourParentFragment: Fragment(), DialogCloseListener {
override fun handleDialogClose(dialog: DialogInterface) {
// do something
}
}

现在转到对话框片段。实现 onDismiss 方法。在其中,检查父片段是否实现了您的接口,调用您的方法,并在其中传递必要的参数:

    override fun onDismiss(dialog: DialogInterface) {
super.onDismiss(dialog)
if(parentFragment is DialogCloseListener){
(parentFragment as DialogCloseListener).handleDialogClose(dialog)
}
}

我认为这种方法很好,因为您可以跟踪特定的关闭事件(通过向方法传递特定的参数) ,例如,取消订单,并以某种方式处理它。

试试这个

dialog.setOnDismissListener {
Log.e("example","example")
}

玩得开心!