Android Numberpicker 小数
Posted
技术标签:
【中文标题】Android Numberpicker 小数【英文标题】:Android Numberpicker decimals 【发布时间】:2016-09-30 01:06:25 【问题描述】:我正在尝试在 android 中创建一个数字选择器,但***只增加 1。我想增加 0.1。我在网上查了一下,但我发现一个格式化的浮点数组禁用了***。请帮助并为语法感到抱歉,我正在学习。
【问题讨论】:
或者你可以有 2 个号码选择器。一个用于单位,另一个用于小数。 【参考方案1】:您可以使用自定义字符串来做到这一点:
NumberPicker picker = new NumberPicker(this);
picker.setMinValue(0);
picker.setMaxValue(100);
picker.setDisplayedValues( new String[] "0.0", "0.1", ..., "10.0" );
double = picker.getValue() / 10.0;
【讨论】:
但是如果最大值是100,我是否必须创建一个自定义字符串到100,比如0.1、0.2...99.8、99.9、100? 然后我会使用两个微调器甚至编辑字段。一个微调器的用户体验真的很糟糕 这是一个解决方案,但是 numberpicker 不能被格式化为以小数递增? 我不明白,你已经问过了。不,它仅适用于整数 好的,我会接受你的解决方案。【参考方案2】:您可以根据ElegantNumberButton 创建自己的 DecimalPicker 视图。 将以下类添加到您的项目中:
/path/to/your/DecimalPicker.java
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
import java.util.Locale;
import ru.alanov.cashbox.R;
import ru.alanov.cashbox.Utils;
public class DecimalPicker extends RelativeLayout
private Context context;
private AttributeSet attrs;
private int styleAttr;
private OnClickListener mListener;
private double initialNumber, finalNumber, lastNumber, currentNumber;
private EditText editText;
private String format;
private OnValueChangeListener onValueChangeListener;
public DecimalPicker(Context context)
super(context);
this.context = context;
initView();
public DecimalPicker(Context context, AttributeSet attrs)
super(context, attrs);
this.context = context;
this.attrs = attrs;
initView();
public DecimalPicker(Context context, AttributeSet attrs, int defStyleAttr)
super(context, attrs, defStyleAttr);
this.context = context;
this.attrs = attrs;
this.styleAttr = defStyleAttr;
initView();
private void initView()
inflate(context, R.layout.decimal_picker, this);
final Resources res = getResources();
final int defaultColor = res.getColor(R.color.colorPrimary);
final int defaultTextColor = res.getColor(R.color.colorText);
final Drawable defaultDrawable = res.getDrawable(R.drawable.decimal_picker_shape);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DecimalPicker, styleAttr, 0);
initialNumber = a.getInt(R.styleable.DecimalPicker_initialNumber, 0);
finalNumber = a.getInt(R.styleable.DecimalPicker_finalNumber, Integer.MAX_VALUE);
float textSize = a.getDimension(R.styleable.DecimalPicker_textSize, 24);
int color = a.getColor(R.styleable.DecimalPicker_backGroundColor,defaultColor);
int textColor = a.getColor(R.styleable.DecimalPicker_textColor,defaultTextColor);
Drawable drawable = a.getDrawable(R.styleable.DecimalPicker_backgroundDrawable);
Button buttonMinus = (Button) findViewById(R.id.subtract_btn);
Button buttonPlus = (Button) findViewById(R.id.add_btn);
editText = (EditText) findViewById(R.id.number_counter);
editText.setOnEditorActionListener(new TextView.OnEditorActionListener()
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event)
if (actionId == EditorInfo.IME_ACTION_DONE || actionId == EditorInfo.IME_ACTION_NEXT)
String num = ((EditText) v).getText().toString();
setNumber(num, true);
return false;
);
editText.addTextChangedListener(new TextWatcher()
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after)
@Override
public void onTextChanged(CharSequence s, int start, int before, int count)
@Override
public void afterTextChanged(Editable s)
String value = s.toString().trim();
double valueDouble = -1;
try
valueDouble = parseDouble(value.isEmpty() ? "0" : value);
catch (NumberFormatException e)
e.printStackTrace();
if (valueDouble >= 0)
lastNumber = currentNumber;
currentNumber = valueDouble;
callListener(DecimalPicker.this);
);
LinearLayout mLayout = (LinearLayout) findViewById(R.id.decimal_picker_layout);
buttonMinus.setTextColor(textColor);
buttonPlus.setTextColor(textColor);
editText.setTextColor(textColor);
buttonMinus.setTextSize(textSize);
buttonPlus.setTextSize(textSize);
editText.setTextSize(textSize);
if (drawable == null)
drawable = defaultDrawable;
assert drawable != null;
drawable.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.SRC));
if (Build.VERSION.SDK_INT > 16)
mLayout.setBackground(drawable);
else
mLayout.setBackgroundDrawable(drawable);
editText.setText(String.valueOf(initialNumber));
currentNumber = initialNumber;
lastNumber = initialNumber;
buttonMinus.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View mView)
double num = parseDouble(editText.getText().toString());
setNumber(String.valueOf(num - 1)/*, true*/);
);
buttonPlus.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View mView)
double num = parseDouble(editText.getText().toString());
setNumber(String.valueOf(num + 1)/*, true*/);
);
a.recycle();
private void callListener(View view)
if (mListener != null)
mListener.onClick(view);
if (onValueChangeListener != null && lastNumber != currentNumber)
onValueChangeListener.onValueChange(this, lastNumber, currentNumber);
public String getNumber()
return String.valueOf(currentNumber);
public void setNumber(String number)
try
double n = parseDouble(number);
if (n > finalNumber)
n = finalNumber;
if (n < initialNumber)
n = initialNumber;
if (format != null)
String num = String.format(Utils.getCurrentLocale(getContext()), format, n);
num = removeTrailingZeroes(num);
editText.setText(num);
else
editText.setText(String.valueOf(number));
lastNumber = currentNumber;
currentNumber = parseDouble(editText.getText().toString());
catch (NumberFormatException e)
e.printStackTrace();
private double parseDouble(String str) throws NumberFormatException
return Double.parseDouble(str.replace(",","."));
private String removeTrailingZeroes(String num)
NumberFormat nf = NumberFormat.getInstance();
if (nf instanceof DecimalFormat)
DecimalFormatSymbols sym = ((DecimalFormat) nf).getDecimalFormatSymbols();
char decSeparator = sym.getDecimalSeparator();
String[] split = num.split((decSeparator == '.' ? "\\" : "") + String.valueOf(decSeparator));
if (split.length == 2 && split[1].replace("0", "").isEmpty())
num = split[0];
return num;
public void setNumber(String number, boolean notifyListener)
setNumber(number);
if (notifyListener)
callListener(this);
public void setOnClickListener(OnClickListener onClickListener)
mListener = onClickListener;
public void setOnValueChangeListener(OnValueChangeListener onValueChangeListener)
this.onValueChangeListener = onValueChangeListener;
public interface OnClickListener
void onClick(View view);
public interface OnValueChangeListener
void onValueChange(DecimalPicker view, double oldValue, double newValue);
public void setRange(Double startingNumber, Double endingNumber)
initialNumber = startingNumber;
finalNumber = endingNumber;
public void setFormat(String format)
this.format = format;
/layout/decimal_picker.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_gravity="center_horizontal"
android:layout_
android:id="@+id/decimal_picker_layout"
android:layout_>
<Button
android:id="@+id/subtract_btn"
android:layout_weight="1"
android:layout_
android:layout_
android:text="-"
android:background="@android:color/transparent" />
<EditText
android:id="@+id/number_counter"
android:gravity="center"
android:imeOptions="flagNoExtractUi"
android:inputType="numberDecimal"
android:text = "1"
android:layout_weight="1"
android:layout_
android:layout_
android:background="@android:color/transparent" />
<Button
android:id="@+id/add_btn"
android:layout_weight="1"
android:layout_
android:layout_
android:text="+"
android:background="@android:color/transparent" />
</LinearLayout>
/drawable/decimal_picker_shape.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<corners android:radius="4dp" />
</shape>
/values/attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="DecimalPicker">
<attr name="backGroundColor" format="color"/>
<attr name="initialNumber" format="integer"/>
<attr name="finalNumber" format="integer" />
<attr name="textColor" format="color"/>
<attr name="textSize" format="dimension"/>
<attr name="backgroundDrawable" format="reference"/>
<attr name="decimalFormat" format="reference"/>
</declare-styleable>
</resources>
在/values/colors.xml中添加<color name="colorText">#FFFFFF</color>
使用示例:
在你的活动布局地方
<path.to.your.DecimalPicker
android:id="@+id/decimal_picker"
android:layout_
android:layout_
android:textSize="16sp"/>
在你的Activity#onCreate()
地方
DecimalPicker decimalPicker = (DecimalPicker) view.findViewById(R.id.decimal_picker);
decimalPicker.setFormat("%.3f");//Weight format
decimalPicker.setOnValueChangeListener(new DecimalPicker.OnValueChangeListener()
@Override
public void onValueChange(DecimalPicker picker, double oldValue, double newValue)
//Do what you want to handle value change.
);
努力的结果: 单击 +/- 将更改数字的整数部分。如果您想更改小数部分 - 单击数字并手动编辑。如果没有小数部分,您将看到只有没有零的整数部分。
【讨论】:
【参考方案3】:或者,您可以使用这个方便的NumberPicker
Kotlin 扩展对话框,它将您的Double
值缩放到合适的Int
范围并将Int
值转换回Double
s 之前调用任何回调。它基本上隐藏了NumberPicker
仅支持Int
并增加了对Double
的支持!
这是您需要复制和粘贴的片段扩展:
fun Fragment.showNumberPickerDialog(
title: String,
value: Double,
range: ClosedRange<Double>,
stepSize: Double,
formatToString: (Double) -> String,
valueChooseAction: (Double) -> Unit
)
val numberPicker = NumberPicker(context).apply
setFormatter formatToString(it.toDouble() * stepSize)
wrapSelectorWheel = false
minValue = (range.start / stepSize).toInt()
maxValue = (range.endInclusive / stepSize).toInt()
this.value = (value.toDouble() / stepSize).toInt()
// NOTE: workaround for a bug that rendered the selected value wrong until user scrolled, see also: https://***.com/q/27343772/3451975
(NumberPicker::class.java.getDeclaredField("mInputText").apply isAccessible = true .get(this) as EditText).filters = emptyArray()
MaterialAlertDialogBuilder(context)
.setTitle(title)
.setView(numberPicker)
.setPositiveButton("OK") _, _ -> valueChooseAction(numberPicker.value.toDouble() * stepSize)
.setNeutralButton("Cancel") _, _ -> /* do nothing, closes dialog automatically */
.show()
然后像这样使用它:
showNumberPickerDialog(
title = "Your Weight",
value = 75.0, // in kilograms
range = 10.0 .. 300.0,
formatToString = "$it kg" ,
valueChooseAction = saveNewWeight(it)
)
【讨论】:
这几乎对我有用,除非stepSize = 0.1
我会得到更长的值,比如4.5
很好,但4.6
会出现4.6000000000000005
,然后是@987654336 @ 会很好,但4.8
不会。我也不确定如何让NumberPickerDialog
出现,除非使用button
,最好从spinner
或其他输入字段中做到这一点
@Devnsyde 随意查看我如何在项目中使用我的代码,因为它是开源的:github.com/Flinesoft/FitnessTracker-Android/… 请注意,我的项目中没有遇到任何此类问题。希望对您有所帮助!以上是关于Android Numberpicker 小数的主要内容,如果未能解决你的问题,请参考以下文章
Android零基础入门第58节:数值选择器NumberPicker
我正在尝试使用 Android NumberPicker 小部件,但我不知道如何从 NumberPicker 设置值