Múltiples DatePickers en la misma actividad

Soy absolutamente nuevo en la plataforma Android y he estado creando una aplicación mientras aprendía el proceso de desarrollo.

Actualmente, estoy trabajando en una actividad en la que necesito implementar 2 recolectores de fechas. Una es una “Fecha de inicio” y la otra es una “Fecha de finalización”. He estado siguiendo el tutorial de DatePicker en la página de desarrolladores de Android aquí: http://developer.android.com/resources/tutorials/views/hello-datepicker.html

Para un DatePicker, funciona bien.

Ahora mi problema es que cuando reproduzco todo el proceso para un segundo selector de fecha, aparece bien en el emulador y en el teléfono. Pero cuando no importa qué botón presiono para seleccionar las fechas, solo se actualiza el primer TextView y el segundo TextView sigue mostrando la fecha actual.

Aquí está el código:

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(" ")); } 

/ * la callback recibida cuando el usuario “establece” la fecha en el diálogo para la función de fecha de inicio * /

  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; } 

}

Por favor asesórese sobre los cambios requeridos para el código.

Necesita hacer 2 cuadros de diálogo DatePicker por separado

Hacer 2 oyentes

 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; 

Implementarlos …

  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) { ..... } }; 

Crear cuadros de diálogo separados para ambos

 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; } 

Tengo una solución que permite un número ilimitado de campos de fecha sin agregar nuevos tipos de diálogo. Cuando el usuario hace clic en uno de los botones, registro qué TextView y Calendario se están modificando actualmente antes de iniciar DatePickerDialog. El OnDateSetListener del diálogo luego actualiza el TextView y el Calendario registrados.

 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; } } } 

Este tipo de flexibilidad es útil en una aplicación en la que no se sabe cuántos selectores de fecha necesitará hasta el tiempo de ejecución.

Ampliando la opción de Adam en una interpretación de peso ligeramente más ligero y potencialmente más útil, decidí mantener una referencia int para la ID del elemento que creó una instancia de la solicitud de diálogo y luego hacer referencia a eso en el controlador de evento final. Esto tiene la ventaja adicional de encajar perfectamente en una statement de conmutación en este método en caso de que tenga múltiples entradas de fecha pero desee un formato específico para cada grupo de cada una. Todos los fragmentos a continuación están en mi clase de actividad directamente

Variables de instancia

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

Controlador de diálogo

 @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); } }; 

Manejador de selección de fecha

 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; } } }; 

Creo que encontré una solución más limpia. Es una mezcla entre lo que aconseja Google y los comentarios que leo aquí. En mi caso, incluso funciona cuando se llama desde el fragmento de Viewpager. Básicamente, transfiero un conjunto de argumentos al fragmento de diálogo cuando llamo al selector desde mi fragmento, como se define aquí: Android: paso datos (extras) a un fragmento Luego recupero el valor del paquete en mi clase DialogFragment, y enciendo es valioso.

Aquí están los dos oyentes de mis botones startDate y endDate, de mi código Fragment:

  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"); } }); 

Aquí está mi clase DatePickerFragment

 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(" ")); } } 

}

puedes usar simplemente este tipo

 public class MainActivity 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.activity_main); /* 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; } } } 

No estaba satisfecho con ninguna de las soluciones mencionadas anteriormente, así que hice lo mío de la siguiente manera: https://gist.github.com/JoachimR/f82b2b371b1ced4a09918c970e045d4f

 import android.app.DatePickerDialog import android.app.Dialog import android.os.Bundle import android.support.v4.app.DialogFragment import java.util.* class ChooseDayDialog : DialogFragment() { companion object { private val KEY_INITIAL_TIMESTAMP = "KEY_INITIAL_TIMESTAMP" private val KEY_REQUEST_CODE = "KEY_REQUEST_CODE" private val DEFAULT_REQUEST_CODE = 20 fun createInstance(initialTimestamp: Long, requestCode: Int = DEFAULT_REQUEST_CODE) = ChooseDayDialog().apply { arguments = Bundle().apply { putLong(KEY_INITIAL_TIMESTAMP, initialTimestamp) putInt(KEY_REQUEST_CODE, requestCode) } } } interface OnDayChosenListener { fun onDayChosen(requestCode: Int, year: Int, month: Int, dayOfMonth: Int) } private lateinit var listener: OnDayChosenListener override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val activity = activity if (activity is OnDayChosenListener) { listener = activity } else { throw IllegalStateException("Activity must implement OnDayChosenListener") } } override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { val timestamp = arguments?.getLong(KEY_INITIAL_TIMESTAMP, -1L) ?: -1L if (timestamp == -1L) { throw IllegalStateException("no initial time given") } val requestCode = arguments?.getInt(KEY_REQUEST_CODE, DEFAULT_REQUEST_CODE) ?: DEFAULT_REQUEST_CODE val calendar = Calendar.getInstance().apply { timeInMillis = timestamp } return DatePickerDialog(activity, DatePickerDialog.OnDateSetListener { _, year, month, dayOfMonth -> listener.onDayChosen(requestCode, year, month, dayOfMonth) }, calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH)) } } 

simplemente haz una variable booleana en mainActivity como esta ::

 private boolean startDateOrEndDAte = true; 

luego haga que los oyentes seleccionen botones como este y cambie el valor de la variable para el botón evrey ::

 DialogFragment datePicker = new DatePickerFragment(); attendDate.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { datePicker.show(getSupportFragmentManager(),"Date Picker"); startOrEnd = true ; } }); leaveDate.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { datePicker.show(getSupportFragmentManager(),"Date Picker"); startOrEnd = false ; } }); 

luego, en el método onDateSet, solo agregue una statement como esta ::

 public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) { Calendar c = Calendar.getInstance(); c.set(Calendar.YEAR, year); c.set(Calendar.MONTH, month); c.set(Calendar.DAY_OF_MONTH, dayOfMonth); String date = DateFormat.getDateInstance().format(c.getTime()); attendDate = findViewById(R.id.attend_date); leaveDate = findViewById(R.id.leave_date); if (startOrEnd) { attendDate.setText(date); } else { leaveDate.setText(date); } } 

solo puedes usar el siguiente código

 @Override protected Dialog onCreateDialog(int id) { /* * final Dialog d = new Dialog(this); d.set */ switch (id) { case DATE_DIALOG_ID: return new DatePickerDialog(this, android.R.style.Theme_Holo_Light_Dialog_MinWidth, mDateSetListener, cmYear, cmMonth, cmDay); } return null; } private DatePickerDialog.OnDateSetListener mDateSetListener = new DatePickerDialog.OnDateSetListener() { @Override public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) { cmYear = year; cmMonth = monthOfYear; cmDay = dayOfMonth; updateDisplay(); } }; private void updateDisplay() { String date_check = "" + new StringBuilder() // Month is 0 based so add 1 .append(cmYear).append("-").append(cmMonth + 1) .append("-").append(cmDay).append(" "); } 

puede llamar a Dialog en cualquier onclick

 showDialog(DATE_DIALOG_ID); 

donde DATE_DIALOG_ID se declara como

 static final int DATE_DIALOG_ID = 0; 

Espero que esto sea útil.

intente con este código. Desde y hasta que los botones aparecen al hacer clic en, se muestra un cuadro de diálogo de selector de fecha y la fecha seleccionada se utiliza para establecer las vistas de texto.

  From.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // new DatePickerDialog(TripPlanner.this, from_dateListener, from_year, from_month, from_day).show(); new DatePickerDialog(TripPlanner.this, R.style.DialogTheme, new DatePickerDialog.OnDateSetListener() { @Override public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) { //DO SOMETHING Fromdate.setText(String.valueOf(dayOfMonth)+"/"+String.valueOf(monthOfYear+1)+"/"+String.valueOf(year)); } }, 2015, 02, 26).show(); } }); To.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { new DatePickerDialog(TripPlanner.this, R.style.DialogTheme, new DatePickerDialog.OnDateSetListener() { @Override public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) { //DO SOMETHING Todate.setText(String.valueOf(dayOfMonth)+"/"+String.valueOf(monthOfYear+1)+"/"+String.valueOf(year)); } }, 2015, 02, 26).show(); } }); 

Simplemente puede usar una variable de indicador booleano para determinar la vista desde la que realiza la llamada.