Reputation: 10729
I want to allow the user to enter numbers with a decimal separator (comma or dot) depending on the region.
Now I'm using DigitsKeyListener
to enable comma as separator for some locales (e.g. Poland, Germany).
val separator = DecimalFormatSymbols.getInstance().decimalSeparator
editTextValue.keyListener = DigitsKeyListener.getInstance("-0123456789$separator")
This code is written in
kotlin.
If software keyboard is Gboard
or other third party keyboard, then everything is fine and user can use comma or dot as separator.
But when user use stock keyboard and DigitsKeyListener
is set, then not all keys are visible and user is not able to add separator.
This is my EditText code:
<android.support.design.widget.TextInputLayout
android:id="@+id/textInput"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
app:hintTextAppearance="@style/Lorin.Theme.TextInputLayout"
app:layout_constraintLeft_toRightOf="@id/imageInfo"
app:layout_constraintRight_toLeftOf="@id/buttonHistoryNumeric">
<android.support.design.widget.TextInputEditText
android:id="@+id/editTextValue"
style="@style/Lorin.EditText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:imeOptions="flagNavigateNext"
android:inputType="number|numberSigned|numberDecimal"
android:maxLines="1"
tools:hint="Range"/>
</android.support.design.widget.TextInputLayout>
val separator = DecimalFormatSymbols.getInstance().decimalSeparator
//editTextValue.keyListener = DigitsKeyListener.getInstance("-0123456789$separator")
When line with DigitsKeyListener
is commented, key for separator is visible but only available separator is dot
Do you have any ideas how to use comma as separator on stock keyboard?
Upvotes: 2
Views: 2353
Reputation: 11
public class MainActivity extends Activity {
private EditText editText;
private String blockCharacterSet = "~#^|$%&*!";
private InputFilter filter = new InputFilter() {
@Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
if (source != null && blockCharacterSet.contains(("" + source))) {
return "";
}
return null;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editText = (EditText) findViewById(R.id.editText);
editText.setFilters(new InputFilter[] { filter });
}
}
Upvotes: 0
Reputation: 4775
I had the same problem once. The stock keyboards on Samsung devices are horrible... There is just no way to display a numeric keyboard with a comma.
The best solution I found was just replacing the dot with a comma via a TextWatcher
.
But only if the decimal separator of the default locale is a comma.
Allow both dot(.) and comma(,) in digits
and set inputType to numberDecimal
in XML:
<EditText
android:id="@+id/editText_price"
android:layout_marginLeft="8dp"
android:layout_marginStart="8dp"
android:digits="1234567890,."
android:imeOptions="actionDone"
android:inputType="numberDecimal" />
And then add the TextWatcher
to this editText:
val separator = DecimalFormatSymbols.getInstance().decimalSeparator
if (separator == ',') {
editText_price.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) = Unit
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) = Unit
override fun afterTextChanged(s: Editable?) {
if (s.toString().contains(".")) {
val replaced = s.toString().replace('.', separator)
editText_price.setText(replaced)
editText_price.setSelection(replaced.length)
}
}
})
}
Then to get the actual number of the String use this:
try {
val price = DecimalFormat.getInstance().parse(editTextPrice.text.toString());
} catch (e: ParseException) {
e.printStackTrace()
editText_price.setError(getString(R.string.error))
}
Upvotes: 2
Reputation: 2106
The problem is that DigitsKeyListener does not specify the decimal/signed flag when using getInstance with a string of accepted characters. Since KeyListener overrides the input type of the EditText, after setting the KeyListener, your EditText now has inputType number and not numberDecimal or numberSigned.
Since DigitsKeyListener is quite useful, a simple fix is to simply delegate to it but use the correct input type. In Kotlin, this is amazingly easy:
class DecimalSignedDigitsKeyListener(digitsKeyListener: DigitsKeyListener) :
KeyListener by digitsKeyListener {
override fun getInputType() =
InputType.TYPE_CLASS_NUMBER or
InputType.TYPE_NUMBER_FLAG_DECIMAL or
InputType.TYPE_NUMBER_FLAG_SIGNED
}
val separator = DecimalFormatSymbols.getInstance().decimalSeparator
val digitsKeyListener = DigitsKeyListener.getInstance("<your digits>")
editTextValue.keyListener = DecimalSignedDigitsKeyListener(digitsKeyListener)
I'd recommend always accepting '.' in addition to any locale-specific separator, since not all keyboards will actually show the comma or other symbols.
Upvotes: 4