I am absolutely new to the Android platform and have been building an application while learning the development process.
Currently, I am working on an activity in which i need to deploy 2 date pickers. One is a "Start Date" and the other is an "End date". I have been following the DatePicker tutorial on the android developers page here: http://developer.android.com/resources/tutorials/views/hello-datepicker.html
For one DatePicker, it works just fine.
Now my problem is, when I replicate the whole process for a second date picker, it shows up just fine on the emulator as well as on the handset. But when no matter which button I press to select the dates, only the first TextView is updated and the second TextView keeps showing the current date.
Here is the code:
package com.datepicker;
import java.util.Calendar;
import android.app.Activity;
import android.app.DatePickerDialog;
import android.app.Dialog;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.TextView;
public class datepicker extends Activity {
private TextView mDateDisplay;
private TextView endDateDisplay;
private Button mPickDate;
private Button endPickDate;
private int mYear;
private int mMonth;
private int mDay;
static final int START_DATE_DIALOG_ID = 0;
static final int END_DATE_DIALOG_ID = 0;
/** Called when the activity is first created. */
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
/* capture our View elements for the start date function */
mDateDisplay = (TextView) findViewById(R.id.startdateDisplay);
mPickDate = (Button) findViewById(R.id.startpickDate);
/* add a click listener to the button */
mPickDate.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
showDialog(START_DATE_DIALOG_ID);
}
});
/* get the current date */
final Calendar c = Calendar.getInstance();
mYear = c.get(Calendar.YEAR);
mMonth = c.get(Calendar.MONTH);
mDay = c.get(Calendar.DAY_OF_MONTH);
/* display the current date (this method is below) */
updateStartDisplay();
/* capture our View elements for the end date function */
endDateDisplay = (TextView) findViewById(R.id.enddateDisplay);
endPickDate = (Button) findViewById(R.id.endpickDate);
/* add a click listener to the button */
endPickDate.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
showDialog(END_DATE_DIALOG_ID);
}
});
/* get the current date */
final Calendar c1 = Calendar.getInstance();
mYear = c1.get(Calendar.YEAR);
mMonth = c1.get(Calendar.MONTH);
mDay = c1.get(Calendar.DAY_OF_MONTH);
/* display the current date (this method is below) */
updateEndDisplay();
}
private void updateEndDisplay() {
endDateDisplay.setText(
new StringBuilder()
// Month is 0 based so add 1
.append(mMonth + 1).append("-")
.append(mDay).append("-")
.append(mYear).append(" "));
}
private void updateStartDisplay() {
mDateDisplay.setText(
new StringBuilder()
// Month is 0 based so add 1
.append(mMonth + 1).append("-")
.append(mDay).append("-")
.append(mYear).append(" "));
}
/* the callback received when the user "sets" the date in the dialog for the start date function */
private DatePickerDialog.OnDateSetListener mDateSetListener =
new DatePickerDialog.OnDateSetListener() {
public void onDateSet(DatePicker view, int year,
int monthOfYear, int dayOfMonth) {
mYear = year;
mMonth = monthOfYear;
mDay = dayOfMonth;
updateStartDisplay();
}
};
@Override
protected Dialog onCreateDialog(int id) {
switch (id) {
case START_DATE_DIALOG_ID:
return new DatePickerDialog(this,
mDateSetListener,
mYear, mMonth, mDay);
}
return null;
}
/* the callback received when the user "sets" the date in the dialog for the end date function */
private DatePickerDialog.OnDateSetListener endDateSetListener =
new DatePickerDialog.OnDateSetListener() {
public void onDateSet(DatePicker view, int year,
int monthOfYear, int dayOfMonth) {
mYear = year;
mMonth = monthOfYear;
mDay = dayOfMonth;
updateStartDisplay();
}
};
protected Dialog onCreateDialog1(int id) {
switch (id) {
case END_DATE_DIALOG_ID:
return new DatePickerDialog(this,
endDateSetListener,
mYear, mMonth, mDay);
}
return null;
}
}
Please advise on the changes required for the code.
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
private static final int DIALOG_DATE_PICKER = 100;
private int datePickerInput;
@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;
}
private OnClickListener datePickerListener =
new OnClickListener()
{
@Override
public void onClick(View v)
{
datePickerInput = v.getId();
showDialog(DIALOG_DATE_PICKER);
}
};
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;
}
}
};
I think I've found a cleaner solution. It's a mix between what's advised by Google and the comments I read here. In my case, It's even working when called from a Viewpager's fragment. Basically, I pass a bundle of arguments to the dialog fragment when calling the picker dialog from my fragment, as defined here : Android: Pass data(extras) to a fragment Then I get back the bundle value in my DialogFragment class, and switch on its value.
Here are the two listeners of both my startDate and endDate buttons, from my Fragment code :
mWylStartDate.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Bundle bundle = new Bundle();
bundle.putInt("DATE",1);
DialogFragment newFragment = new DatePickerFragment();
newFragment.setArguments(bundle);
newFragment.show(getFragmentManager(), "datePicker");
}
});
mWylEndDate.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Bundle bundle = new Bundle();
bundle.putInt("DATE",2);
DialogFragment newFragment = new DatePickerFragment();
newFragment.setArguments(bundle);
newFragment.show(getFragmentManager(), "datePicker");
}
});
Here's my DatePickerFragment class
public class DatePickerFragment extends DialogFragment implements DatePickerDialog.OnDateSetListener
{
static final int START_DATE = 1;
static final int END_DATE = 2;
private int mChosenDate;
int cur = 0;
@Override
public Dialog onCreateDialog(Bundle savedInstanceState)
{
// Use the current date as the default date in the picker
final Calendar c = Calendar.getInstance();
int year = c.get(Calendar.YEAR);
int month = c.get(Calendar.MONTH);
int day = c.get(Calendar.DAY_OF_MONTH);
Bundle bundle = this.getArguments();
if (bundle != null)
{
mChosenDate = bundle.getInt("DATE", 1);
}
switch (mChosenDate)
{
case START_DATE:
cur = START_DATE;
return new DatePickerDialog(getActivity(), this, year, month, day);
case END_DATE:
cur = END_DATE;
return new DatePickerDialog(getActivity(), this, year, month, day);
}
return null;
}
@Override
public void onDateSet(DatePicker datePicker, int year, int month, int day)
{
if (cur == START_DATE)
{
// set selected date into textview
Log.v("Date Début", "Date1 : " + new StringBuilder().append(month + 1)
.append("-").append(day).append("-").append(year)
.append(" "));
} else
{
Log.v("Date fin", "Date2 : " + new StringBuilder().append(month + 1)
.append("-").append(day).append("-").append(year)
.append(" "));
}
}
}
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