我有一个AlertDialog
与Activites
工作正常,但由于AlertDialog.Builder(getActivity)
它不适用于Fragments。在这种情况下,父Activity包含一个使用Fragment
显示记录的子RecyclerView
。当用户滑动记录时,会显示AlertDialog
以确认删除。但是,这不起作用,因为AlertDialog
引用了父Activity。我已经在下面的AlertFragment代码中包含了AlertDialog的代码和LogCat输出。
我在子Fragment中实例化ConfirmDialogFragment,如下所示:
DialogFragment confirmDialog = new ConfirmDialogFragment();
confirmDialog.show(getFragmentManager(), "ConfirmDialogFragment");
AlertDialog片段代码如下所示:
package com.example.jbiss.petminder.dialogs;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.util.Log;
import androidx.fragment.app.DialogFragment;
import com.example.jbiss.petminder.R;
import java.util.Set;
public class ConfirmDialogFragment extends DialogFragment {
private static final String TAG = "ConfirmDialogFragment";
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Log.d(TAG, "Entered onCreateDialog");
if(savedInstanceState ==null){
Log.d(TAG, "savedInstanceState is null");
}else{
Set<String> s = savedInstanceState.keySet();
Log.d(TAG, "savedInstanceState is: " + s);
}
Log.d(TAG, "getParentFragment is: " + getParentFragment());
Log.d(TAG, "getContext is: " + getContext());
Log.d(TAG, "getActivity is: " + getActivity());
Log.d(TAG, "this is: " + this);
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setMessage(R.string.delete_confirm)
.setPositiveButton(R.string.delete, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
Log.d(TAG, "Delete clicked");
Log.d(TAG, "getContext is: " + getContext());
Log.d(TAG, "this is: " + this);
mListener.onDialogPositiveClick(ConfirmDialogFragment.this);
}
})
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// User cancelled the dialog
Log.d(TAG, "Cancel clicked");
mListener.onDialogNegativeClick(ConfirmDialogFragment.this);
}
});
return builder.create();
}
public interface ConfirmDialogListener {
public void onDialogPositiveClick(DialogFragment dialog);
public void onDialogNegativeClick(DialogFragment dialog);
}
// Use this instance of the interface to deliver action events
ConfirmDialogListener mListener;
// Override the Fragment.onAttach() method to instantiate the ConfirmDialogListener
@Override
public void onAttach(Context context) {
super.onAttach(context);
Log.d(TAG, "Entered onAttach");
// Verify that the host activity implements the callback interface
try {
// Instantiate the NoticeDialogListener so we can send events to the host
mListener = (ConfirmDialogListener) context;
Log.d(TAG, "activity is: " + context);
Log.d(TAG, "mListener is: " + mListener);
} catch (ClassCastException e) {
// The activity doesn't implement the interface, throw exception
throw new ClassCastException(context.toString()
+ " must implement NoticeDialogListener");
}
}
}
代码中显示的LogCat输出如下所示。
MedicalInformationFragment: swiped to the 4!
MedicalInformationFragment: position swiped is: 0
ConfirmDialogFragment: Entered onAttach
ConfirmDialogFragment: activity is: com.example.jbiss.petminder.activities.PetInformationActivity@8963dda
ConfirmDialogFragment: mListener is: com.example.jbiss.petminder.activities.PetInformationActivity@8963dda
ConfirmDialogFragment: Entered onCreateDialog
ConfirmDialogFragment: savedInstanceState is null
ConfirmDialogFragment: getParentFragment is: null
ConfirmDialogFragment: getContext is: com.example.jbiss.petminder.activities.PetInformationActivity@8963dda
ConfirmDialogFragment: getActivity is: com.example.jbiss.petminder.activities.PetInformationActivity@8963dda
ConfirmDialogFragment: this is: ConfirmDialogFragment{a4e01a0 #2 ConfirmDialogFragment}
单击ConfirmDialogFragment的Delete时,LogCat将显示以下内容:
ConfirmDialogFragment: Delete clicked
ConfirmDialogFragment: getContext is: com.example.jbiss.petminder.activities.PetInformationActivity@8963dda
ConfirmDialogFragment: this is: com.example.jbiss.petminder.dialogs.ConfirmDialogFragment$2@c3512d0
PetInformationActivity: Entered onDialogPositiveClick
PetInformationViewModel: Entered: deletePetName
从LogCat输出中可以看出,ConfirmDialogFragment确实返回到调用Fragment Confirm DialogFragment.ConfirmDialog Listener Interface方法,它转到父Activity的。
这是因为AlertDialog.Builder
用getActivity()
实例化,它获得了父Activity的引用,而不是调用Fragment的引用。从LogCat输出中可以看出,尝试使用getContext也引用了父Activity。所有关于使用AlertDialog
的问题都表明使用getActivity,因为它们似乎是关于使用DialogFragment
,而不是关于片段调用它。
AlertDialog是否打算从片段中使用?是否有一个Fragment等同于Activity的引用,可以传递给AlertDialog的构造函数,如下所示?
DialogFragment confirmDialog = new ConfirmDialogFragment(CallingFragmentReferenceSimilarToAnActivity);
confirmDialog.show(getFragmentManager(), "ConfirmDialogFragment");
在这种情况下,我应该能够重载AlertDialog的构造函数,我相信。
这是因为AlertDialog.Builder是用getActivity()实例化的,它获取父Activity的引用,而不是调用Fragment的引用。
问题不在于AlertDialog
,而在于你的听众是如何设置的。由于Fragment
的getContext()
方法返回父亲Activity
的上下文。
mListener = (ConfirmDialogListener) context;
此行将您的侦听器设置为调用Activity
的父Fragment
。不必将mListener
设置为父活动,而是必须将其设置为调用片段。
首先,您必须在实例化时为DialogFragment
设置目标片段。
DialogFragment confirmDialog = new ConfirmDialogFragment();
confirmDialog.setTargetFragment(this, "CONFIRM_DIALOG_TAG");
if (getFragmentManager() != null) {
confirmDialog.show(getFragmentManager(), "ConfirmDialogFragment");
}
现在,在对话框片段的onCreate
中,您可以将回调设置为您的片段。
try {
mListener = (ConfirmDialogListener) getTargetFragment();
} catch (ClassCastException e) {
throw new ClassCastException(context.toString()
+ " must implement ConfirmDialogListener");
}
并从onAttach
方法中删除代码。