I try to implement a callback from a DialogFragment
.
There is a good example, but they don't open this DialogFragment
from a Fragment
.
http://developer.android.com/guide/topics/ui/dialogs.html#PassingEvents
So here is my code:
public class EditDateDialogFragment extends DialogFragment {
// Use this instance of the interface to deliver action events
EditDateDialogListener mListener;
/* The activity that creates an instance of this dialog fragment must
* implement this interface in order to receive event callbacks.
* Each method passes the DialogFragment in case the host needs to query it. */
public interface EditDateDialogListener {
public void onDialogPositiveClick(DialogFragment dialog);
public void onDialogNegativeClick(DialogFragment dialog);
}
public static EditDateDialogFragment newInstance( int currentCategoryId ) {
EditDateDialogFragment p = new EditDateDialogFragment();
Bundle args = new Bundle();
args.putInt("currentRecordId", currentCategoryId);
p.setArguments(args);
return p;
}
@Override
public void onCreate(Bundle savedInstanceState) {
mCurrentRecordId = getArguments().getInt("currentRecordId");
super.onCreate(savedInstanceState);
}
public void onAttach(SherlockActivity activity) {
super.onAttach(activity);
try {
// Instantiate the EditDateDialogListener so we can send events to the host
mListener = (EditDateDialogListener) activity;
} catch (ClassCastException e) {
// The activity doesn't implement the interface, throw exception
throw new ClassCastException(activity.toString() + " must implement EditDateDialogListener");
}
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
LayoutInflater inflater = LayoutInflater.from(getActivity());
final View v = inflater.inflate(R.layout.fragment_dialog_edit_date, null);
return new AlertDialog.Builder(getActivity()).setTitle("Set Date...").setView(v).setCancelable(true).setPositiveButton("Confirm", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Log.d("", "Dialog confirmed");
mListener.onDialogPositiveClick(EditDateDialogFragment.this);
}
}).setNegativeButton("Abort", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Log.d("", "Dialog abort");
dialog.cancel();
}
}).create();
}
}
In RecordDetailFragment.java i implement the interface and create a new instance of the EditDateDialogFragment at this way (just the important parts):
public class RecordDetailFragment extends SherlockFragment implements EditDateDialogFragment.EditDateDialogListener {
...
DialogFragment editDateFragment = EditDateDialogFragment.newInstance( recordId );
editDateFragment.show(getActivity().getSupportFragmentManager(), "EditDateDialogFrame");
@Override
public void onDialogPositiveClick(DialogFragment dialog) {
LOGD(TAG, "Overriden Dialog confirmed");
//((EditDateDialogFragment) dialog).mDatePicker;
}
@Override
public void onDialogNegativeClick(DialogFragment dialog) {
// TODO Auto-generated method stub
}
...
}
Now the public void onAttach(SherlockActivity activity)
in the EditDateDialogFragment
is never called, because I create the DialogFragment
from a Fragment
instead of an Activity
?
How to fix this?
UPDATE: In the RecordDetailFragment I insert this into the onCreate()
if (savedInstanceState != null) {
EditDateDialogFragment dpf = (EditDateDialogFragment) getActivity().getSupportFragmentManager().findFragmentByTag("EditDateDialogFragment");
if (dpf != null) {
dpf.setListener((EditDateDialogListener) this);
}
}
I changed the instantiation of the DialogFragment to
EditDateDialogFragment editDateFragment = EditDateDialogFragment.newInstance( recordId );
editDateFragment.setListener((EditDateDialogListener) this);
editDateFragment.show(getActivity().getSupportFragmentManager(), "EditDateDialogFragment");
Note the EditDateDialogFragment instead of DialogFragment. I'm not sure how to update the reference in the dialog.
Just jumped into the same problem, the solution was very simple. Instead of overriding
public void onAttach(Context context) {}
override this:
public void onAttach(Activity activity) {}
Everything is now fine with DialogFragment
.
How to fix this?
I'm guessing that you want the RecordDetailFragment
instance to behave as the EditDateDialogListener
for the DialogFragment
. If yes then you need to explicitly set it(and update it) as the listener:
DialogFragment editDateFragment = EditDateDialogFragment.newInstance( recordId );
editDataFragment.setListener(RecordDetailFragment.this);
editDateFragment.show(getActivity().getSupportFragmentManager(), "EditDateDialogFrame");
Where setListener()
is a method in the EditDialogFragment
like this:
public void setListener(EditDateDialogListener listener) {
mListener = listener;
}
As the user rotates the phone, for example, the Activity along with its fragments will be recreated and you need to re set the listener to point to the newly created RecordDetailFragment
instance(you may want to use a WeakReference
for mListener
). Something similar you can find in this answer(you'll look for the two fragments in the onCreate
).
Edit: In the onCreate
method of the Activity
:
if (savedInstanceState != null) {
RecordDetailFragment df = (RecordDetailFragment) getSupportFragmentManager().findFragmentByTag("rdf"); // "rdf" is the tag used when you add the RecordDetailFragment to the activity
EditDateDialogFragment s = (EditDateDialogFragment) getSupportFragmentManager().findFragmentByTag("tag"); // "tag" is the string set as the tag for the dialog when you show it
if (s != null) {
// the dialog exists so update its listener
s.setListener(df);
}
}
Somewhere in the onCreateDialog cast the mListener to the getActivity():
try {
mListener = (EditDateDialogListener) getActivity();
} catch (Exception e) {
throw new ClassCastException(getActivity().toString()
+ " must implement EditDateDialogListener");
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With