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);
26
demandé sur Sebastian 2013-07-17 23:15:06

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.

22
répondu dgel 2017-05-23 12:02:37

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]);
17
répondu torvin 2017-05-23 10:31:29

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.

10
répondu Lumbi 2014-03-04 21:59:11

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

3
répondu HeNRGi 2013-12-11 19:05:12

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:

  1. 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);
      }
    }
    
  2. 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;
     }
    }
    
3
répondu Sebastian 2018-03-07 21:45:38

J'ai réussi à le réparer en appelant

picker.invalidate();

Juste après avoir défini le formateur.

1
répondu user1504495 2014-11-04 12:00:20

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.

1
répondu Christopher Chua 2018-05-29 23:38:33