Multiple DatePickers in same activity

I have a solution that allows for an unlimited number of date fields without adding new dialog types. When the user clicks one of the buttons, I register which TextView and Calendar is currently being modified before launching the DatePickerDialog. The dialog's OnDateSetListener then updates the registered TextView and Calendar.

import java.util.Calendar;

import android.app.Activity;
import android.app.DatePickerDialog;
import android.app.Dialog;
import android.app.DatePickerDialog.OnDateSetListener;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.TextView;

public class MultiDatePickerActivity extends Activity {

    private TextView startDateDisplay;
    private TextView endDateDisplay;
    private Button startPickDate;
    private Button endPickDate;
    private Calendar startDate;
    private Calendar endDate;

    static final int DATE_DIALOG_ID = 0;

    private TextView activeDateDisplay;
    private Calendar activeDate;

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.multidatepicker);

        /*  capture our View elements for the start date function   */
        startDateDisplay = (TextView) findViewById(R.id.startDateDisplay);
        startPickDate = (Button) findViewById(R.id.startPickDate);

        /* get the current date */
        startDate = Calendar.getInstance();

        /* add a click listener to the button   */
        startPickDate.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                showDateDialog(startDateDisplay, startDate);
            }
        });

        /* capture our View elements for the end date function */
        endDateDisplay = (TextView) findViewById(R.id.endDateDisplay);
        endPickDate = (Button) findViewById(R.id.endPickDate);

        /* get the current date */
        endDate = Calendar.getInstance();

        /* add a click listener to the button   */
        endPickDate.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                showDateDialog(endDateDisplay, endDate);
            }
        });

        /* display the current date (this method is below)  */
        updateDisplay(startDateDisplay, startDate);
        updateDisplay(endDateDisplay, endDate);
    }

    private void updateDisplay(TextView dateDisplay, Calendar date) {
        dateDisplay.setText(
                new StringBuilder()
                    // Month is 0 based so add 1
                    .append(date.get(Calendar.MONTH) + 1).append("-")
                    .append(date.get(Calendar.DAY_OF_MONTH)).append("-")
                    .append(date.get(Calendar.YEAR)).append(" "));

    }

    public void showDateDialog(TextView dateDisplay, Calendar date) {
        activeDateDisplay = dateDisplay;
        activeDate = date;
        showDialog(DATE_DIALOG_ID);
    }

    private OnDateSetListener dateSetListener = new OnDateSetListener() {
        @Override
        public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
            activeDate.set(Calendar.YEAR, year);
            activeDate.set(Calendar.MONTH, monthOfYear);
            activeDate.set(Calendar.DAY_OF_MONTH, dayOfMonth);
            updateDisplay(activeDateDisplay, activeDate);
            unregisterDateDisplay();
        }
    };

    private void unregisterDateDisplay() {
        activeDateDisplay = null;
        activeDate = null;
    }

    @Override
    protected Dialog onCreateDialog(int id) {
        switch (id) {
            case DATE_DIALOG_ID:
                return new DatePickerDialog(this, dateSetListener, activeDate.get(Calendar.YEAR), activeDate.get(Calendar.MONTH), activeDate.get(Calendar.DAY_OF_MONTH));
        }
        return null;
    }

    @Override
    protected void onPrepareDialog(int id, Dialog dialog) {
        super.onPrepareDialog(id, dialog);
        switch (id) {
            case DATE_DIALOG_ID:
                ((DatePickerDialog) dialog).updateDate(activeDate.get(Calendar.YEAR), activeDate.get(Calendar.MONTH), activeDate.get(Calendar.DAY_OF_MONTH));
                break;
        }
    }
}

This kind of flexibility is useful in an application where you don't know how many date pickers you will need until runtime.


You need to make 2 separate DatePicker Dialogs

Make 2 Listeners

int from_year, from_month, from_day,to_year, to_month, to_day; //initialize them to current date in onStart()/onCreate()
DatePickerDialog.OnDateSetListener from_dateListener,to_dateListener;

Implement them...

         from_dateListener = new OnDateSetListener(){

            public void onDateSet(DatePicker arg0, int arg1, int arg2, int arg3) {

                          ...

                }
            }

        };
        to_dateListener = new OnDateSetListener(){
            public void onDateSet(DatePicker arg0, int arg1, int arg2, int arg3) {
                .....
            }
        };

Create Seperate Dialogs for both of them

int DATE_PICKER_TO = 0;
int DATE_PICKER_FROM = 1;

@Override
protected Dialog onCreateDialog(int id) {

    switch(id){
        case DATE_PICKER_FROM:
                return new DatePickerDialog(this, from_dateListener, from_year, from_month, from_day); 
            case DATE_PICKER_TO:
                return new DatePickerDialog(this, to_dateListener, to_year, to_month, to_day);
    }
        return null;
}

Expanding Adam's option into an slightly lighter weight interpretation and potentially more useful, I decided to maintain an int reference for the element ID that instantiated the dialog request and then just referenced that in the final event handler. This has the added benefit of fitting nicely into a switch statement in this method in case you have multiple date inputs but want specific formatting for each or groups of each. All snippets below are in my Activity class directly

Instance variables

private static final int        DIALOG_DATE_PICKER  = 100;
private int                     datePickerInput;

Dialog Handler

@Override
public Dialog onCreateDialog(int id)
{
    switch(id) {
        case DIALOG_DATE_PICKER:
            final Calendar c = Calendar.getInstance();
            DatePickerDialog dialog = new DatePickerDialog(this, dateSetListener, c.get(Calendar.YEAR), c.get(Calendar.MONTH), c.get(Calendar.DAY_OF_MONTH));
            return dialog;
    }
    return null;
}

Click Listener

private OnClickListener datePickerListener =
    new OnClickListener()
{
    @Override
    public void onClick(View v)
    {
        datePickerInput = v.getId();
        showDialog(DIALOG_DATE_PICKER);
    }
};

Date Selection Handler

private DatePickerDialog.OnDateSetListener dateSetListener =
    new DatePickerDialog.OnDateSetListener()
{
    @Override
    public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth)
    {
        switch( datePickerInput ) {
            case R.id.datePicker1:
                ((EditText) findViewById( datePickerInput ))
                    .setText(...);
                ...
                break;
            case R.id.datePicker2:
                ...
                break;
            default:
                ...
                break;
        }
    }
};