Я пытаюсь создать модифицированный NumberPicker для двойных/плавающих значений с настройкой приращения и точности, чтобы я мог увеличивать значения чем-то другим, кроме 1. Для моих случаев использования у меня есть приложение калькулятора, которое я хочу использовать 2-3 из эти NumberPickers для ввода/выбора двойного значения. Некоторые входные данные могут быть порядка 10 000 000, а другие могут быть небольшими, например 0,0001, поэтому мне нужно иметь возможность регулировать шаг приращения, а также точность для каждого средства выбора. Поскольку может быть очень большой диапазон значений, я не хочу использовать setDisplayedValues. Я также хочу разрешить пользователю вводить числа непосредственно через EditText на NumberPicker.
Это то, что у меня есть для моего класса NumberPickerDouble:
import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.text.InputFilter;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.NumberPicker;
import java.math.BigDecimal;
public class NumberPickerDouble extends NumberPicker {
private double mPrecision = 1;
private double mIncrement = 1;
private EditText numberEditText;
private boolean shouldDisableEditText = true; //set to true to disable edit text input and focus
public NumberPickerDouble(Context context) {
super(context);
}
public NumberPickerDouble(Context context, AttributeSet attrs) {
super(context, attrs);
init(attrs);
}
public NumberPickerDouble(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(attrs);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public NumberPickerDouble(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(attrs);
}
private void init(AttributeSet attrs){
numberEditText = populateEditText((ViewGroup) this);
if (numberEditText != null && shouldDisableEditText)
numberEditText.setFocusable(false);
processAttributeSet(attrs);
}
public void setPrecision(double precision){
mPrecision = precision;
}
public double getPrecision(){
return mPrecision;
}
public void setIncrement(double increment) {
mIncrement = increment;
setFormat();
}
public double getIncrement(){
return mIncrement;
}
public String getValueFormat(){
int decimalPlaces = BigDecimal.valueOf(mPrecision).scale();
if (decimalPlaces > 0)
return "%." + String.valueOf(decimalPlaces) + "f";
else
return "%d";
}
public void setDoubleValue(double value){
setValue((int)(value / mIncrement));
numberEditText.setFilters(new InputFilter[0]);
}
private void setFormat() {
NumberPicker.Formatter formatter = new NumberPicker.Formatter(){
@Override
public String format(int value) {
double temp = value * mIncrement;
int precision = BigDecimal.valueOf(mPrecision).scale();
String newValue;
if (precision > 0)
newValue = String.format("%." + precision +"f", temp);
else
newValue = "" + temp;
return newValue;
}
};
setFormatter(formatter);
}
private EditText populateEditText(ViewGroup viewGroup) {
int count = viewGroup.getChildCount();
for (int i = 0; i < count; i++) {
final View child = viewGroup.getChildAt(i);
if (child instanceof ViewGroup)
populateEditText((ViewGroup) child);
else if (child instanceof EditText)
return (EditText) child;
}
return null;
}
private void processAttributeSet(AttributeSet attrs) {
}
}
Приращение и точность работают, как и ожидалось, для считывания, но у меня есть две проблемы:
При первой инициализации представления NumberPickers неправильно форматирует первое значение и либо пропускает десятичное число, либо ничего не отображает (см. изображение ниже). Как только я прокручиваю средство выбора, оно исчезает. Я попробовал некоторые из предложенных решений в этом опубликовать, но ничего не работает. Форматор NumberPicker не работает при первом рендеринге
Я не могу вводить числа в EditText NumberPicker, но даже если бы я мог, я не могу понять, как лучше всего перехватить входное значение, чтобы разделить его на приращение, как в моем методе setDoubleValue.
Вот как я настраиваю NumberPickers на изображении выше:
final NumberPickerDouble np1 = (NumberPickerDouble) v.findViewById(R.id.numPicker1);
final NumberPickerDouble np2 = (NumberPickerDouble) v.findViewById(R.id.numPicker2);
final NumberPickerDouble np3 = (NumberPickerDouble) v.findViewById(R.id.numPicker3);
np1.setMaxValue(1000000);
np2.setMaxValue(200000);
np3.setMaxValue(200);
np1.setMinValue(0);
np2.setMinValue(0);
np3.setMinValue(0);
np1.setPrecision(1);
np2.setPrecision(1);
np3.setPrecision(0.001);
np1.setIncrement(100);
np2.setIncrement(1);
np3.setIncrement(0.002);
np1.setWrapSelectorWheel(false);
np2.setWrapSelectorWheel(false);
np3.setWrapSelectorWheel(false);
np1.setDoubleValue(0);
np1.setDoubleValue(0);
np1.setDoubleValue(0);