library - Android NumberPicker con Formatter no se formatea en la primera representación
number spinner android (7)
Tengo un NumberPicker que tiene un formateador que formatea los números mostrados cuando el NumberPicker gira o cuando se ingresa un valor manualmente. Esto funciona bien, pero cuando se muestra por primera vez NumberPicker y lo inicializo con setValue(0)
el 0 no se formatea (debería aparecer como "-" en lugar de 0). Tan pronto como gire el NumberPicker desde ese punto, todo funcionará.
¿Cómo puedo obligar a NumberPicker a formatear siempre, tanto en la primera representación como también cuando ingreso un número manualmente con el teclado?
Este es mi formateador
public class PickerFormatter implements Formatter {
private String mSingle;
private String mMultiple;
public PickerFormatter(String single, String multiple) {
mSingle = single;
mMultiple = multiple;
}
@Override
public String format(int num) {
if (num == 0) {
return "-";
}
if (num == 1) {
return num + " " + mSingle;
}
return num + " " + mMultiple;
}
}
Agrego mi formateador al selector con setFormatter()
, esto es todo lo que hago al selector.
picker.setMaxValue(max);
picker.setMinValue(min);
picker.setFormatter(new PickerFormatter(single, multiple));
picker.setWrapSelectorWheel(wrap);
La respuesta proporcionada por NoActivity funcionó para mí, pero solo tenía que hacer:
View firstItem = bugFixNumberPicker.getChildAt(0);
if (firstItem != null) {
firstItem.setVisibility(View.INVISIBLE);
}
para solucionar el problema. No necesitaba subclase NumberPicker. No vi el problema donde los elementos del selector desaparecen al tocarlos.
La siguiente solución funcionó para mí para las API 18-26 sin usar reflexión y sin usar setDisplayedValues()
.
Consiste en dos pasos:
Asegúrese de que el primer elemento se muestre configurando su visibilidad en invisible (utilicé el Inspector de diseño para ver la diferencia con cuando se muestra, no es lógico, pero
View.INVISIBLE
realidad hace que la vista sea visible).private void initNumberPicker() { // Inflate or create your BugFixNumberPicker class // Do your initialization on bugFixNumberPicker... bugFixNumberPicker.setFormatter(new NumberPicker.Formatter() { @Override public String format(final int value) { // Format to your needs return aFormatMethod(value); } }); // Fix for bug in Android Picker where the first element is not shown View firstItem = bugFixNumberPicker.getChildAt(0); if (firstItem != null) { firstItem.setVisibility(View.INVISIBLE); } }
Subclase NumberPicker y asegúrese de que no se produzcan eventos de clics para que no ocurra el problema de que los elementos del selector desaparezcan al tocar.
public class BugFixNumberPicker extends NumberPicker { public BugFixNumberPicker(Context context) { super(context); } public BugFixNumberPicker(Context context, AttributeSet attrs) { super(context, attrs); } public BugFixNumberPicker(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override public boolean performClick() { return false; } @Override public boolean performLongClick() { return false; } @Override public boolean onInterceptTouchEvent(MotionEvent event) { return false; } }
Llamar al método privado changeValueByOne()
través de la reflexión como se describe en una respuesta anterior, funciona para mí en el API Level 16
(Android 4.1.2 y superior), pero no parece ayudar en el API Level 15
(Android 4.0.3), sin embargo !
Lo que me funciona en el Nivel de API 15 (y superior) es usar su propio formateador personalizado para crear una matriz de cadenas y pasarlo con el método setDisplayedValues()
al selector de números.
Ver también: Ejemplo de Android 3.x y 4.x NumberPicker
Me las arreglé para arreglarlo llamando
picker.invalidate();
Justo después de configurar el formateador.
También me encontré con este pequeño code.google.com/p/android/issues/detail?id=35482 molesto. Usé una técnica de esta respuesta para encontrar una solución desagradable pero efectiva.
NumberPicker picker = (NumberPicker)view.findViewById(id.picker);
picker.setMinValue(1);
picker.setMaxValue(5);
picker.setWrapSelectorWheel(false);
picker.setFormatter(new NumberPicker.Formatter() {
@Override
public String format(int value) {
return my_formatter(value);
}
});
try {
Method method = picker.getClass().getDeclaredMethod("changeValueByOne", boolean.class);
method.setAccessible(true);
method.invoke(picker, true);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
Llamar a ese método privado changeValueByOne
inmediatamente después de crear una instancia de mi selector de números parece patear al formateador lo suficiente como para comportarse como debería. El selector de números aparece agradable y limpio con el primer valor formateado correctamente. Como he dicho, desagradable pero eficaz.
Tuve el mismo problema y utilicé el método setDisplayedValues()
lugar.
int max = 99;
String[] values = new String[99];
values[0] = “-” + mSingle
values[1] =
for(int i=2; i<=max; i++){
makeNames[i] = String.valueOf(i) + mMultiple;
}
picker.setMinValue(0);
picker.setMaxValue(max);
picker.setDisplayedValues(values)
Sin embargo, esto no le permite al usuario establecer el valor manualmente en el selector.
La solución de dgel no funciona para mí: cuando toco el selector, el formato desaparece nuevamente. Este error es causado por el filtro de entrada establecido en EditText
dentro de NumberPicker
cuando setDisplayValues
no se usa. Así que se me ocurrió esta solución:
Field f = NumberPicker.class.getDeclaredField("mInputText");
f.setAccessible(true);
EditText inputText = (EditText)f.get(mPicker);
inputText.setFilters(new InputFilter[0]);