web-dev-qa-db-ja.com

Android FormatPを使用したNumberPickerが最初のレンダリングでフォーマットされない

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

}
_

フォーマッタをsetFormatter()を使用してピッカーに追加します。これがピッカーに対して行うすべてのことです。

_    picker.setMaxValue(max);
    picker.setMinValue(min);
    picker.setFormatter(new PickerFormatter(single, multiple));
    picker.setWrapSelectorWheel(wrap);
_
32
A. Steenbergen

私はこの迷惑な小さな バグ にも遭遇しました。 この答え の手法を使用して、厄介ですが効果的な修正を行いました。

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

番号ピッカーをインスタンス化した直後にそのプライベートchangeValueByOneメソッドを呼び出すと、フォーマッターが動作するのに十分なほどキックされます。数値ピッカーが起動し、最初の値が正しくフォーマットされています。私が言ったように、厄介ですが効果的です。

27
dgel

dgelのソリューション が機能しません。ピッカーをタップすると、書式設定が再び表示されなくなります。このバグは、EditTextが使用されていないときにNumberPicker内のsetDisplayValuesに設定された入力フィルターが原因で発生します。だから私はこの回避策を思いついた:

Field f = NumberPicker.class.getDeclaredField("mInputText");
f.setAccessible(true);
EditText inputText = (EditText)f.get(mPicker);
inputText.setFilters(new InputFilter[0]);
25
torvin

同じ問題があり、代わりに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)

ただし、ユーザーがピッカーで手動で値を設定することはできません。

11
Lumbi

次の解決策は、API 18-26 リフレクションを使用せずに、およびsetDisplayedValues()を使用せずに私にとってうまくいきました。

これは2つのステップで構成されています。

  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);
      }
    }
    
  2. 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;
     }
    }
    
6
Sebastian

以前の回答で説明したリフレクションを介したプライベートメソッドchangeValueByOne()の呼び出しは、_API Level 16_(Android 4.1.2以降)では機能しますが、_API Level 15_では役に立たないようです(Android 4.0.3)ただし、!

APIレベル15以上で機能するのは、独自のカスタムフォーマッタを使用して文字列配列を作成し、それをメソッドsetDisplayedValues()で数値ピッカーに渡すことです。

参照: Android 3.xおよび4.x NumberPickerの例

4
HeNRGi

NoActivityによって提供された答えは私にとってはうまくいきましたが、私はしなければなりませんでした:

View firstItem = bugFixNumberPicker.getChildAt(0);
if (firstItem != null) {
  firstItem.setVisibility(View.INVISIBLE);
}

問題を修正します。 NumberPickerをサブクラス化する必要はありませんでした。私はピッカー要素がタッチで消える問題を見ませんでした。

3

torvin および Sebastian による回答に基づいた私の解決策を次に示します。何かをサブクラス化したり、リフレクションを使用したりする必要はありません。

View editView = numberPicker.getChildAt(0);

if (editView != null && editView instanceof EditText) {
    // Remove default input filter
    ((EditText) editView).setFilters(new InputFilter[0]);
}
3
Nikolai

私は電話でそれをなんとか修正しました

picker.invalidate();

フォーマッタを設定した直後。

1
user1504495