[英]DialogFragment timepicker onCancel and onDismiss problem
[英]DialogFragment and onDismiss
我正在使用DialogFragment
,我從Activity
顯示如下:
DialogFragmentImage dialog = DialogFragmentImage.newInstance(createBitmap());
dialog.onDismiss(dialog);.onDismiss(this);
dialog.show(getFragmentManager(), "DialogFragmentImage");
我想檢查DialogFragment
被解除(例如按下后退按鈕時),但在我的Activity
中。 我怎樣才能做到這一點? 如何“告訴”我的activity
DialogFragment
已被解除?
讓你的 Activity 實現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);
}
}
}
這是我的答案。 有點晚了,但可能對路過的人有好處。
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 工作。 否則調用setOnDismissListener()
時可能會發生NullPointerException
。
如有錯誤請見諒。 希望這有幫助。
這是一個老問題,但我沒有找到滿意的解決方案。 我不喜歡將任何偵聽器傳遞給我的 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);
替代答案,如果您無權訪問活動的 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(...);
}
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);
});
如果您不喜歡@yaroslav-mytkalyk 的解決方案,其中片段需要強制轉換活動/父片段,這里還有一個:
這是想法:
DialogFragmentImage
中公開一個偵聽器。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's re-created.
@Nullable MyFragment myFragment = (MyFragment) getSupportFragmentManager().findFragmentByTag(MY_FRAGMENT_TAG);
if (myFragment != null) {
myFragment.setOnDismissListener(null);
}
super.onStop();
}
}
注意:所有示例都不正確,因為您的片段應該有一個無參數構造函數!
片段本身中帶有后退手勢和關閉按鈕的工作代碼。 我刪除了無用的代碼內容,例如在onCreate
中獲取 arg 等。
重要提示:當方向改變時也會調用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;
}
}
現在如何從父級調用它。
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
您可以繼承 DialogFragment 並提供您自己的偵聽器,該偵聽器將被調用並在 onCancel 中。
var onDismissListener: (() -> Unit)? = null
對於不熟悉 Kotlin 的人來說,這只是一個匿名接口,可以在 Java 中保存樣板 iterface。 在 Java 中使用字段和設置器。
然后在 onCancel
override fun onCancel(dialog: DialogInterface?) {
super.onCancel(dialog)
onDismissListener?.invoke()
}
玩得開心!
科特林答案
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.
}
}
使用 kotlin 和附加接口的解決方案。 (此處將顯示片段的示例,但進行一些更改后,它也可以在活動中工作)
首先你需要創建一個接口(參數集可以是任意的):
interface DialogCloseListener {
fun handleDialogClose(dialog: DialogInterface)
}
然后在調用 DailogFragment 的 Fragment 中實現這個接口:
class YourParentFragment: Fragment(), DialogCloseListener {
override fun handleDialogClose(dialog: DialogInterface) {
// do something
}
}
現在轉到您的 DialogFragment。 實現 onDismiss 方法。 在其中,檢查父片段是否實現了您的接口,調用您的方法,並在那里傳遞必要的參數:
override fun onDismiss(dialog: DialogInterface) {
super.onDismiss(dialog)
if(parentFragment is DialogCloseListener){
(parentFragment as DialogCloseListener).handleDialogClose(dialog)
}
}
我認為這種方式很好,因為您可以跟蹤特定的關閉事件(通過將某個參數傳遞給方法),例如取消訂單,並以某種方式處理它。
嘗試這個
dialog.setOnDismissListener { Log.e("example","example") }
玩得開心!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.