Android NumberPicker avec formateur ne formate pas sur le premier Rendu
J'ai un NumberPicker qui a un formateur qui formate les nombres affichés soit quand le NumberPicker tourne ou quand une valeur est entrée manuellement. Cela fonctionne bien, mais lorsque le NumberPicker est affiché pour la première fois et que je l'initialise avec setValue(0)
, le 0 n'est pas formaté (il devrait s'afficher comme " - " au lieu de 0). Dès que je fais tourner le NumberPicker à partir de ce point, tout fonctionne.
Comment puis-je forcer le NumberPicker à formater toujours-à la fois lors du premier rendu et aussi lorsque j'entre un numéro manuellement avec le clavier?
C'est mon formateur
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;
}
}
J'ajoute mon formateur au sélecteur avec setFormatter()
, c'est tout ce que je fais au sélecteur.
picker.setMaxValue(max);
picker.setMinValue(min);
picker.setFormatter(new PickerFormatter(single, multiple));
picker.setWrapSelectorWheel(wrap);
7 réponses
J'ai aussi rencontré ce petit bug ennuyeux . Utilisé une technique de cette réponse pour trouver une solution méchante mais efficace.
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();
}
Appeler cette méthode privée changeValueByOne
immédiatement après l'instanciation de mon sélecteur de numéros semble donner un coup de pied au formateur pour se comporter comme il le devrait. Le sélecteur de nombre arrive bien et propre avec la première valeur formatée correctement. Comme je l'ai dit, méchant mais efficace.
La solution de Dgel ne fonctionne pas pour moi: lorsque je tape sur le sélecteur, le formatage disparaît à nouveau. Ce bug est causé par le filtre d'entrée défini sur EditText
à l'intérieur de NumberPicker
Lorsque setDisplayValues
n'est pas utilisé. Donc, je suis venu avec cette solution de contournement:
Field f = NumberPicker.class.getDeclaredField("mInputText");
f.setAccessible(true);
EditText inputText = (EditText)f.get(mPicker);
inputText.setFilters(new InputFilter[0]);
J'ai eu le même problème et j'ai utilisé la méthode setDisplayedValues()
à la place.
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)
Cela ne permet pas à l'utilisateur de définir la valeur manuellement dans le sélecteur.
Appeler la méthode privée changeValueByOne()
via la réflexion comme décrit dans une réponse précédente fonctionne pour moi sur API Level 16
(Android 4.1.2 et plus), mais cela ne semble pas aider sur API Level 15
(Android 4.0.3), cependant!
Ce qui fonctionne pour moi au niveau API 15 (et plus) est d'utiliser votre propre formateur personnalisé pour créer un tableau de chaînes et le transmettre avec la méthode setDisplayedValues()
au sélecteur de nombres.
Voir aussi: Android 3.x et 4.x NumberPicker exemple
La solution suivante a fonctionné pour moi pour les API 18-26 sans utiliser reflection , et sans utiliser setDisplayedValues()
.
, Il se compose de deux étapes:
-
Assurez-vous que le premier élément Montre en définissant sa visibilité sur invisible (j'ai utilisé Layout Inspector pour voir la différence avec quand il montre, ce n'est pas logique mais
View.INVISIBLE
rend réellement la vue 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); } }
-
Sous-classe NumberPicker et assurez-vous qu'aucun événement de clic ne passe donc le problème où les éléments du sélecteur disparaissent au toucher ne peut pas arriver.
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; } }
J'ai réussi à le réparer en appelant
picker.invalidate();
Juste après avoir défini le formateur.
La réponse fournie par NoActivity a fonctionné pour moi mais je n'avais qu'à faire:
View firstItem = bugFixNumberPicker.getChildAt(0);
if (firstItem != null) {
firstItem.setVisibility(View.INVISIBLE);
}
Pour résoudre le problème. Je n'avais pas besoin de sous-classer NumberPicker. Je n'ai pas vu le problème où les éléments du sélecteur disparaissent au toucher.