Android DatePickerDialog and the DialogFragment

Introduction:

Starting with Honeycomb and continuing in Ice Cream Sandwich, the Android SDK has introduced several new UI concepts to support larger screens such as tablets. Perhaps the most notable new UI feature is theFragment. Along with the updates to move developers towards fragments and size-independent layouts, Google has deprecated the methods commonly used to display Dialogs from Activities (seeActivity.showDialog() and Activity.onCreateDialog()). These methods were convient; displaying any type of Dialog was possible by simply overridingonCreateDialog(). In order to provide a better user experience when displaying dialogs from Fragments, Google has provided theDialogFragment. I have yet to find any decent tutorials working with DialogFragments, butthis code sample provided in the DialogFragment reference suffices.

I began to utilize this sample to provide a DatePickerDialog via DialogFragment. There exists one glaring problem with this code sample and applying it to a DatePicker: We need callbacks! After the user selects a date, we need to do something with that date. I set off to work up a useful DialogFragment that displayed a DatePicker.

My Solution:

Based on the sample code provided by Google, I came with up with a reusable DialogFragment that provided all the necessary DatePicker functionality. I could have continued with their theme and added the callback interface to the static inner class, but this will be far too reusable to nest it in some later irrelevant Activity. I instead went with a first class….class approach to be a little more flexible. On with it!

Step 1: Create a new class

Create a new class which inherits from DialogFragment and define a newInstance() method. Not much goes on in newInstance(), just some initialization.

public class DateDialogFragment extends DialogFragment {
 
    public static String TAG = "DateDialogFragment";
 
    static Context sContext;
    static Calendar sDate;
    static DateDialogFragmentListener sListener;
 
    public static DateDialogFragment newInstance(Context context, int titleResource, Calendar date){
		DateDialogFragment dialog  = new DateDialogFragment();
 
	sContext = context;
        sDate = date;
 
	Bundle args = new Bundle();
	args.putInt("title", titleResource);
	dialog.setArguments(args);
	return dialog;
    }
}


Step 2: Implement onCreateDialog()

Here’s where we can return the DatePickerDialog.

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    return new DatePickerDialog(sContext, dateSetListener, sDate.get(Calendar.YEAR), sDate.get(Calendar.MONTH), sDate.get(Calendar.DAY_OF_MONTH));
}



Note dateSetListener being passed as the callback, I will detail this later.

Step 3: Define callback interface

Our DateDialogFragment needs a way to report back to its calling Fragment or Activity so we define an interface with a single callback method.

public interface DateDialogFragmentListener{
    public void dateDialogFragmentDateSet(Calendar date);
}

We also give callers a setDateDialogFragmentListener() method.

public void setDateDialogFragmentListener(DateDialogFragmentListener listener){
    sListener = listener;
}


Here’s what it looks like from the Activity or Fragment.

//create a new DateDialogFragment
DateDialogFragment ddf = DateDialogFragment.newInstance(this, R.string.set_date, date);
 
//assign a new DateDialogFragmentListener
ddf.setDateDialogFragmentListener(new DateDialogFragmentListener() {
    //fired when user selects date
    @Override
    public void dateDialogFragmentDateSet(Calendar date) {
        // update the fragment
        mDateDetailFragment.updateDate(date);
    }
});


Step 4: Connect listeners

Now that we have defined a listener interface for the calling Activity or Fragment to receive notifications from our custom DateDialogFragment, we need to connect our DateDialogFragment to theDatePickerDialog we have created inside of it. I alluded to this in Step 2, where thedateSetListener object was being passed in the DatePickerDialog constructor.

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    return new DatePickerDialog(sContext, dateSetListener, sDate.get(Calendar.YEAR), sDate.get(Calendar.MONTH), sDate.get(Calendar.DAY_OF_MONTH));
}


dateSetListener is a DatePickerDialog.OnDateSetListener, the callback interface given to us by the default AndroidDatePickerDialog. In our DateDialogFragment class, we implement this interface and simply fire our own DateDialogFragmentListener.dateDialogFragmentDateSet() (see Step 3), passing along the date from theDatePickerDialog.OnDateSetListener. This completes the marriage between our DateDialogFragment and the DatePickerDialog within.


private DatePickerDialog.OnDateSetListener dateSetListener =
    new DatePickerDialog.OnDateSetListener() {
 
	@Override
	public void onDateSet(DatePicker view, int year, int monthOfYear,
			int dayOfMonth) {
 
                //create new Calendar object for date chosen
                //this is done simply combine the three args into one
		Calendar newDate = Calendar.getInstance();
		newDate.set(year, monthOfYear, dayOfMonth);
		//call back to the DateDialogFragment listener
		sListener.dateDialogFragmentDateSet(newDate);
 
	}
};


Step 5: Show a DateDialogFragment

Now that we have defined our DialogFragment subclass that provides a DatePickerDialog, we can use it by invoking it from an Activity.


//create new DateDialogFragment
DateDialogFragment ddf = DateDialogFragment.newInstance(this, R.string.set_date, date);
 
ddf.setDateDialogFragmentListener(new DateDialogFragmentListener() {
 
    @Override
    public void dateDialogFragmentDateSet(Calendar date) {
        // update the fragment
	mDateDetailFragment.updateDate(date);
    }
});
 
ddf.show(getSupportFragmentManager(), "date picker dialog fragment");


And that does it. You now have a reusable DialogFragment that provides a familiar DatePickerDialog with all its expected behavior.

Note: This solution is backwards compatible for pre-Honeycomb Android. Simply use theAndroid compatibility package.

For complete source code of a simple app that makes use of the DateDialogFragment,click here.


源码:

http://www.kylebeal.com/wp-content/uploads/2011/11/DateDialogFragmentExample.zip

你可能感兴趣的:(Android DatePickerDialog and the DialogFragment)