Wenn man Dialoge in Android benutzen will muss man sie als Fragment an die Activity anbinden.
Die beste Möglichkeit um zwischen Dialog und Activity oder Fragment (an die Activity angebunden, in dem Beispiel RecordDetailFragment) zu kommunizieren sind Callbacks.
Das interface EditDateDialogListener beschreibt 2 Funktionen:
public void onDialogPositiveClick(DialogFragment dialog);
public void onDialogNegativeClick(DialogFragment dialog);
In der Klasse die den Dialog anhängen möchte implementiert man das Interface EditDateDialogListener (public class RecordDetailFragment extends SherlockFragment implements EditDateDialogFragment.EditDateDialogListener).
Die Callbacks sorgen dafür, dass der gesamte Dialog an die Activity zurückgegeben und dort verwendet werden kann.
Diese werden abhängig vom gedrückten Button an die implementierende Klasse geschickt.
Das größte Problem ist die Verbindung von Dialog und angebundener Activity:
Die Activity wird neu erstellt, wenn das Gerät z.B. gedreht wird. Der Dialog schickt nun seine Daten an die nicht mehr vorhandene Activity.
Daher muss diese Verbindung konsistent gehalten werden. Dafür sorgt die setListener Methode, die aufgerufen werden muss sobald man den Dialog anhängt und bei jedem Drehen des Displays (in der onCreate methode implementiert).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | public class EditDateDialogFragment extends DialogFragment { // Use this instance of the interface to deliver action events EditDateDialogListener mListener = new EditDateDialogListener() { @Override public void onDialogPositiveClick(DialogFragment dialog) { // Should always overridden by interface implementing class } @Override public void onDialogNegativeClick(DialogFragment dialog) { // Should always overridden by interface implementing class } }; DatePicker mDatePicker; /* * 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 void setListener(EditDateDialogListener listener) { mListener = listener; } 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); } @Override public Dialog onCreateDialog(Bundle savedInstanceState) { LayoutInflater inflater = LayoutInflater.from(getActivity()); final View v = inflater.inflate(R.layout.fragment_dialog_edit_date, null); mDatePicker = (DatePicker) v.findViewById(R.id.dialog_edit_date); 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"); mListener.onDialogNegativeClick(EditDateDialogFragment.this); dialog.cancel(); } }).create(); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | public class RecordDetailFragment extends SherlockFragment implements EditDateDialogFragment.EditDateDialogListener { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (savedInstanceState != null) { // Update reference // Update reference EditDateDialogFragment attachedDialogFragment = (EditDateDialogFragment) getActivity().getSupportFragmentManager().findFragmentByTag("EditDateDialogFragment"); // "tag" is the string set as the tag for the dialog when you show it if (attachedDialogFragment != null) { // the dialog exists so update its listener attachedDialogFragment.setListener(this); } } } // Called somewhere in the fragment public void showDialog() { EditDateDialogFragment editDateFragment = EditDateDialogFragment.newInstance(recordId); editDateFragment.setListener((EditDateDialogListener) this); editDateFragment.show(getActivity().getSupportFragmentManager(), "EditDateDialogFragment"); } @Override public void onDialogPositiveClick(DialogFragment dialog) { Log.d("RecordDetailFragment", "Callback Dialog confirmed"); int year = ((EditDateDialogFragment) dialog).mDatePicker.getYear(); Log.d("RecordDetailFragment", "Year of DatePicker: " + year); } @Override public void onDialogNegativeClick(DialogFragment dialog) { Log.d("RecordDetailFragment", "Callback Dialog abort"); // TODO Auto-generated method stub } } |
Das Beispiel ist nicht ausreichend erklärt – am besten einbauen und mit dem Debugger durchsteppen.
Es gibt einen guten Guide von Android, der Dialogs erklärt. Speziell habe ich auf die Kommunikation verlinkt. Mein Beispiel unterscheidet sich nicht groß, bis auf das konsistent halten der Callbacks.
Android empfiehlt übrigens solche Abhängigkeiten mit Callbacks zu realisieren.
Außerdem benutzte ich die ActionBarSherlock Library – deshalb die veränderten Activity-Klassen.
Eine falsche Implementierung des Dialogs kann man in der App AdAway sehen. Lädt man die host Einträge herunter erscheint nach Fertigstellung ein Dialog. Dreht man das Gerät verschwindet der Dialog. Offensichtlich besteht keine konsistente Verbindung zwischen Activity und Dialog, die bei uns die setListener übernimmt. Ich kenne den Code nicht und weiß nicht ob Callbacks verwendet wurden, jedoch verhält es sich so, wenn man die Verbindung nicht konsistent hält. Getestet in der AdAway Version 2.0 (39)
If you have found a spelling error, please, notify us by selecting that text and pressing Ctrl+Enter.
2 comments for “Dialog Fragment in Android”