I\'m trying to create an app where the user selects a date from a DatePicker, and then a list is updated with some values.
My GUI looks like this:
Not necessary to add this code under Jelly beans
@Override
public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth){
if (view.isShown()) {
updateDate(year, monthOfYear, dayOfMonth);
}
}
I created a SupportDatePickerDialog.kt class
import android.app.DatePickerDialog
import android.content.Context
import android.os.Build
import android.widget.DatePicker
import androidx.appcompat.view.ContextThemeWrapper
/**
* Support [DatePickerDialog]
* for working around Samsung 5 [java.util.IllegalFormatConversionException] bug.
* > Fatal Exception: java.util.IllegalFormatConversionException: %d can't format java.lang.String arguments
* http://stackoverflow.com/a/31855744/570168
* for OnDateSetListener called twice bug
* https://stackoverflow.com/questions/12436073/datepicker-ondatechangedlistener-called-twice
*
*/
class SupportDateSetListener(private val function: (DatePicker, Int, Int, Int) -> Unit) : DatePickerDialog.OnDateSetListener {
override fun onDateSet(view: DatePicker, year: Int, month: Int, dayOfMonth: Int) {
if (view.isShown) {
function.invoke(view, year, month, dayOfMonth)
}
}
}
class SupportDatePickerDialog(context: Context, listener: SupportDateSetListener, year: Int, month: Int, dayOfMonth: Int) : DatePickerDialog(fixContext(context), listener, year, month, dayOfMonth) {
companion object {
/**
* Wraps the [Context] to use the holo theme to avoid stupid bug on Samsung devices.
*/
@Suppress("DEPRECATION")
private fun fixContext(context: Context): Context {
return if (isBrokenSamsungDevice) {
ContextThemeWrapper(context, android.R.style.Theme_Holo_Light_Dialog)
} else {
context
}
}
/**
* Affected devices:
* - Samsung 5.0
* - Samsung 5.1
*
* @return true if device is affected by this bug.
*/
@Suppress("SpellCheckingInspection")
private val isBrokenSamsungDevice: Boolean
get() = (Build.MANUFACTURER.equals("samsung", ignoreCase = true)
&& Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP_MR1)
}
}
Usage :
val calendar = Calendar.getInstance()
val supportDatePickerDialog = SupportDatePickerDialog(this, SupportDateSetListener { datePicker: DatePicker, year: Int, month: Int, dayOfMonth: Int ->
//TODO
}, calendar[Calendar.YEAR], calendar[Calendar.MONTH], calendar[Calendar.DAY_OF_MONTH])
supportDatePickerDialog.show()
I still haven't managed to find a neat fix. I've rather found a workaround, so the event does not fire twice. The workaround is as follows:
int timesCalled = 1;
private DatePicker.OnDateChangedListener dateSetListener = new DatePicker.OnDateChangedListener() {
public void onDateChanged(DatePicker view, int year, int monthOfYear,
int dayOfMonth) {
Calendar c = Calendar.getInstance();
c.set(year, monthOfYear, dayOfMonth);
timesCalled += 1;
if ((timesCalled % 2) == 0) {
System.out.println ("TEST");
}
}};