I want to swap the Month And Date (Spinners). I want to send the Date column (Spinner) to the left and the Month column (Spinner) to the middle. Is it possible?
According to notes in the source, the order of those NumberPicker
s is determined by the system-wide date format chosen by the user, falling back on a determination of the best order given the user's locale. There is no public method available to easily change this. However, I've figured out a way to change the order regardless.
In the following example, we obtain the IDs for the DatePickerDialog
's NumberPicker
s from the System Resources. The names for these identifiers I found by examining the layout file for the DatePicker
class.
Once we've got the IDs, we find the NumberPicker
s and their parent LinearLayout
in the dialog just like we would any other View
. We can then remove the spinners from the layout, and add them back in any order desired. The DatePicker
class uses the same method to reorder the spinners, and some of the code below is pulled from its source.
After adding back each spinner, we need to call setImeOptions()
with it and its new index in the order. This will correct the focus chain and keyboard feedback for the spinners' input TextView
s.
This all got a little unwieldy, so I wrapped it up in a couple of methods. You need only call the orderDate()
method after your dialog is shown, with a char
array indicating the desired date order. For example:
DatePickerDialog dialog = new DatePickerDialog(...);
...
dialog.show();
orderDate(dialog, new char[]{'d', 'm', 'y'});
We keep an int
constant for the number of spinners, simplifying some of the code pulled from the source:
private static final int SPINNER_COUNT = 3;
private void orderDate(DatePickerDialog dialog, char[] ymdOrder) {
if(!dialog.isShowing()) {
throw new IllegalStateException("Dialog must be showing");
}
final int idYear = Resources.getSystem().getIdentifier("year", "id", "android");
final int idMonth = Resources.getSystem().getIdentifier("month", "id", "android");
final int idDay = Resources.getSystem().getIdentifier("day", "id", "android");
final int idLayout = Resources.getSystem().getIdentifier("pickers", "id", "android");
final NumberPicker spinnerYear = (NumberPicker) dialog.findViewById(idYear);
final NumberPicker spinnerMonth = (NumberPicker) dialog.findViewById(idMonth);
final NumberPicker spinnerDay = (NumberPicker) dialog.findViewById(idDay);
final LinearLayout layout = (LinearLayout) dialog.findViewById(idLayout);
layout.removeAllViews();
for (int i = 0; i < SPINNER_COUNT; i++) {
switch (ymdOrder[i]) {
case 'y':
layout.addView(spinnerYear);
setImeOptions(spinnerYear, i);
break;
case 'm':
layout.addView(spinnerMonth);
setImeOptions(spinnerMonth, i);
break;
case 'd':
layout.addView(spinnerDay);
setImeOptions(spinnerDay, i);
break;
default:
throw new IllegalArgumentException("Invalid char[] ymdOrder");
}
}
}
private void setImeOptions(NumberPicker spinner, int spinnerIndex) {
final int imeOptions;
if (spinnerIndex < SPINNER_COUNT - 1) {
imeOptions = EditorInfo.IME_ACTION_NEXT;
}
else {
imeOptions = EditorInfo.IME_ACTION_DONE;
}
int idPickerInput = Resources.getSystem().getIdentifier("numberpicker_input", "id", "android");
TextView input = (TextView) spinner.findViewById(idPickerInput);
input.setImeOptions(imeOptions);
}
Based on @Mike M. solution I wrote an extension function in Kotlin.
Example:
datePicker.formatDate("dmy") // show picker in Day, Month, Year format
Kotlin extension function:
import android.content.res.Resources
import android.view.View
import android.view.inputmethod.EditorInfo
import android.widget.DatePicker
import android.widget.LinearLayout
import android.widget.NumberPicker
import android.widget.TextView
private const val SPINNER_COUNT = 3
/**
* Changes the [DatePicker] date format.
* Example: dmy will show the date picker in day, month, year order
* */
fun DatePicker.formatDate(ymdOrder: String) {
val system = Resources.getSystem()
val idYear = system.getIdentifier("year", "id", "android")
val idMonth = system.getIdentifier("month", "id", "android")
val idDay = system.getIdentifier("day", "id", "android")
val idLayout = system.getIdentifier("pickers", "id", "android")
val spinnerYear = findViewById<View>(idYear) as NumberPicker
val spinnerMonth = findViewById<View>(idMonth) as NumberPicker
val spinnerDay = findViewById<View>(idDay) as NumberPicker
val layout = findViewById<View>(idLayout) as LinearLayout
layout.removeAllViews()
for (i in 0 until SPINNER_COUNT) {
when (ymdOrder[i]) {
'y' -> {
layout.addView(spinnerYear)
setImeOptions(spinnerYear, i)
}
'm' -> {
layout.addView(spinnerMonth)
setImeOptions(spinnerMonth, i)
}
'd' -> {
layout.addView(spinnerDay)
setImeOptions(spinnerDay, i)
}
else -> throw IllegalArgumentException("Invalid char[] ymdOrder")
}
}
}
private fun setImeOptions(spinner: NumberPicker, spinnerIndex: Int) {
val imeOptions: Int = if (spinnerIndex < SPINNER_COUNT - 1) {
EditorInfo.IME_ACTION_NEXT
} else {
EditorInfo.IME_ACTION_DONE
}
val idPickerInput: Int = Resources.getSystem().getIdentifier("numberpicker_input", "id", "android")
val input = spinner.findViewById<View>(idPickerInput) as TextView
input.imeOptions = imeOptions
}
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