带有Formatter的Android NumberPicker在首次渲染时不会格式化

A. *_*gen 32 android formatter numberpicker android-number-picker

我有一个NumberPicker,它有一个格式化程序,可以在NumberPicker旋转或手动输入值时格式化显示的数字.这工作正常,但是当第一次显示NumberPicker并且我用setValue(0)0 初始化它时没有被格式化(它应该显示为" - "而不是0).一旦我从那一点旋转NumberPicker一切正常.

如何强制NumberPicker始终格式化 - 在第一次渲染时以及在使用键盘手动输入数字时?

这是我的格式化程序

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;
 }

}
Run Code Online (Sandbox Code Playgroud)

我将格式化程序添加到选择器中setFormatter(),这是我对拾取器所做的全部操作.

    picker.setMaxValue(max);
    picker.setMinValue(min);
    picker.setFormatter(new PickerFormatter(single, multiple));
    picker.setWrapSelectorWheel(wrap);
Run Code Online (Sandbox Code Playgroud)

dge*_*gel 27

我也遇到了这个烦人的小虫子.使用这个答案的技术来提出一个讨厌但有效的解决方案.

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();
}
Run Code Online (Sandbox Code Playgroud)

changeValueByOne在实例化我的数字选择器之后立即调用该私有方法似乎使格式化程序足以表现它应该如何.数字选择器出现很好,干净,第一个值格式正确.就像我说的那样,讨厌但有效.

  • 不知何故,在Android编程中,你必须经常使用令人讨厌的黑客攻击. (9认同)
  • 确实 - 这仍然存在于棉花糖:( (4认同)
  • Android 7.1.1和bug似乎仍然完全被忽视. (4认同)
  • 这个错误是在2年前报道的......你在跟我开玩笑吗?android 4.4.2仍然是一个问题 (3认同)
  • 伊隆·马斯克(Elon Musk)向太空发射了特斯拉(tesla),这个问题仍然存在。 (3认同)
  • 对我不起作用:每当我点击选择器时,格式化都会再次消失.我提出了另一个[解决方案](http://stackoverflow.com/a/26797732/332528) (2认同)
  • 对于那些想知道的人,这个bug仍然没有得到解决. (2认同)

tor*_*vin 25

dgel的解决方案对我不起作用:当我点击选择器时,格式化会再次消失.此错误是由未使用时在EditText内部设置的输入过滤器引起的.所以我提出了这个解决方法:NumberPickersetDisplayValues

Field f = NumberPicker.class.getDeclaredField("mInputText");
f.setAccessible(true);
EditText inputText = (EditText)f.get(mPicker);
inputText.setFilters(new InputFilter[0]);
Run Code Online (Sandbox Code Playgroud)


Lum*_*mbi 11

我遇到了同样的问题而且我使用了这个setDisplayedValues()方法.

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)
Run Code Online (Sandbox Code Playgroud)

但这不允许用户在选择器中手动设置值.


Seb*_*ian 6

以下解决方案适用于API 18-26 而不使用反射,并且不使用setDisplayedValues().

它包括两个步骤:

  1. 确保第一个元素通过将其可见性设置为不可见来显示(我使用布局检查器查看显示时的差异,它不合逻辑但View.INVISIBLE实际上使视图可见).

    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);
      }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. Subclass NumberPicker并确保没有点击事件通过,因此拾取元素在触摸时消失的故障不会发生.

    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;
     }
    }
    
    Run Code Online (Sandbox Code Playgroud)


Nik*_*lai 6

这是我基于torvinSebastian的答案的解决方案。您不必继承任何东西或使用反射。

View editView = numberPicker.getChildAt(0);

if (editView instanceof EditText) {
    // Remove default input filter
    ((EditText) editView).setFilters(new InputFilter[0]);
}
Run Code Online (Sandbox Code Playgroud)


Ema*_*lin 3

基于Nikolai答案的 Kotlin 版本

private fun initNumberPicker() {
    nrPicker.children.iterator().forEach {
        if (it is EditText) it.filters = arrayOfNulls(0)    // remove default input filter
    }
}
Run Code Online (Sandbox Code Playgroud)