Как использовать регулярное выражение в android
У меня есть numberDecimal EditText
, который я хочу проверить с помощью регулярного выражения. При проверке я хочу.
-
До десятичной точки максимальная цифра, которую я хочу ввести, равна трем, и цифра не должна начинаться с нуля, как 2,23,342 и т.д.
-
После десятичной точки максимальная цифра, которую я хочу ввести, равна 1,.3,.6 и т.д.
Таким образом, число, которое я разрешаю пользователю вводить, равно 2.1, 32.5, 444.8, 564.9 и т.д.
Но в моем коде что происходит -
-
Это позволяет пользователю вводить более трехзначное число перед десятичной точкой, например 3456, 4444, 5555, и после этого после этого оно не позволяет мне вводить десятичную точку.
-
Это позволяет мне вводить 0 перед десятичной точкой в качестве начала цифры.
Итак, почему это происходит, что-то не так в моем регулярном выражении, которое я использовал. Если кто-нибудь знает, помогите мне решить это.
Код, который я использовал,
weightEditText.addTextChangedListener(new TextWatcher()
{
@Override
public void onTextChanged(CharSequence s, int start, int before, int count){
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after){
}
@Override
public void afterTextChanged(Editable s)
{
Pattern mPattern = Pattern.compile("^([1-9][0-9]{0,2})?(\\.[0-9]?)?$");
Matcher matcher = mPattern.matcher(s.toString());
if(!matcher.find())
{
weightEditText.setText(); // dont know what to place
}
}
});
Ответы
Ответ 1
Никогда не нужно рассматривать только dest
в InputFilter
; что то, что уже присутствует в поле. Измените соответствие регулярного выражения на source
, и было бы уместно, если бы вы только хотели проверить, что определенные символы были приняты в поле. Тем не менее, вы хотите проверить форматирование полей, а не просто фильтровать ввод посимвольной основе. Это намного сложнее.
Каждый раз, когда пользователь вносит изменения в содержимое tempEditText
, система вызывает ваш фильтр filter
до того, как будет произведено изменение. Он передает текущее содержимое поля и предлагаемое изменение (которое может быть вставлено/добавлено, удалено или заменено). Изменение представлено источником CharSequence source
(символы — если any — быть добавленным в поле), индексы начала и конца диапазона в источнике (диапазон не обязательно все source
), a Spanned dest
(текущее содержимое поля перед изменением) и диапазоны dstart и dend indexes в пределах dest
, которые предлагаются для замены указанным диапазоном source
.
Задача filter
состоит в том, чтобы изменить изменение (если необходимо) и вернуть CharSequence
для использования (в полном объеме) вместо source
(или null
для продолжения и использования source
). Вместо проверки dest
, как вы сейчас это делаете, вам нужно будет проверить, приведет ли изменение к допустимому полю. Для этого вам понадобится более сложная логика. (Обратите внимание, в частности, что новый символ может быть предназначен для вставки где-то иначе, чем в конце, а также, filter
будет вызываться, когда пользователь удаляет символы, а также добавляет их.)
Может быть проще реализовать TextWatcher
. В этом методе beforeTextChanged
вы можете записать текущее содержимое и в нем afterTextChanged
метод, вы можете проверить (используя регулярное выражение), приемлемо ли содержимое и если нет, восстановить содержимое до изменения. (Убедитесь, что текст перед изменением был приемлемым.Если это не так, замените что-то приемлемое &mdash, как очистка поля. В противном случае ваш код перейдет в бесконечный цикл, потому что снова будет вызываться TextWatcher
когда вы исправляете содержимое поля.)
У вас также есть ошибка в вашем регулярном выражении: она позволяет вести нулевой уровень. Здесь улучшенная версия, которая устраняет эту проблему (и удаляет один набор ненужных круглых скобок):
"^([1-9][0-9]{0,2})?(\\.[0-9]?)?$"
(В стороне: вы можете использовать \\d
вместо [0-9]
.)
ИЗМЕНИТЬ
Здесь мое редактирование вашего редактирования:
weightEditText.addTextChangedListener(new TextWatcher()
{
private static final Pattern sPattern
= Pattern.compile("^([1-9][0-9]{0,2})?(\\.[0-9]?)?$");
private CharSequence mText;
private boolean isValid(CharSequence s) {
return sPattern.matcher(s).matches();
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count){
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after){
mText = isValid(s) ? new CharSequence(s) : "";
}
@Override
public void afterTextChanged(Editable s)
{
if (!isValid(s))
{
weightEditText.setText(mText);
}
mText = null;
}
});
Ответ 2
Может быть, моя реализация кому-то поможет:
etRepeaterCallsign.addTextChangedListener(new TextWatcher() {
private final Pattern sPattern
= Pattern.compile("^([A-Z]{0,2})?(\\d)?([A-Z-]{0,5})"); // ^([1-9][0-9]{0,2})?(\\.[0-9]?)?$
private CharSequence mText;
private boolean isValid(CharSequence s) {
return sPattern.matcher(s).matches();
}
@Override
public void beforeTextChanged(CharSequence r, int start, int count,
int after) {
mText = r.toString();
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
bIsEdit = true;
}
@Override
public void afterTextChanged(Editable s) {
etRepeaterCallsign.removeTextChangedListener(this);
int iCursorPosition = etRepeaterCallsign.getSelectionStart();
etRepeaterCallsign.setText("");
if (isValid(s))
etRepeaterCallsign.append(s);
else
etRepeaterCallsign.append(mText);
etRepeaterCallsign.setSelection(iCursorPosition);
etRepeaterCallsign.addTextChangedListener(this);
}
});
Ответ 3
Вы можете просто проанализировать номер и проверить, что он равен < 1000, и это число 10 * является целым числом, а num - нет. Вероятно, это было бы более читаемым.
Ответ 4
Вы можете попробовать что-то вроде этого: ^[1-9][0-9]{0,2}(\\.\\d)?$
. Это должно соответствовать любому числу, которое не начинается с 0 (^[1-9]
), а за ним следует не более двух чисел ([0-9]{0,2}
). Регулярное выражение также допускает необязательное десятичное значение ((\\.\\d)?$
).
В идеале вы должны проанализировать строковое значение на double
или float
и сделать все, что нужно сделать, используя фактическое числовое значение.
Чтобы проанализировать ваш string
в значение double
, вам нужно будет использовать Double.parseDouble(String s) так: double myValue = Double.parseDouble(EditText.getText());
Ответ 5
Я попробовал свой шаблон, используя свой код, как показано ниже. Он отлично работает как 2.1, 32.5, 444.8, 564.9 и т.д.
Мой код:
public class WebPush extends Activity {
EditText editTxt;
private TextView regresult;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
editTxt = (EditText) findViewById(R.id.editID);
regresult = (TextView) findViewById(R.id.txtID);
String urName = editTxt.getText().toString();
editTxt.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
}
@Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,int arg3) {
}
@Override
public void afterTextChanged(Editable s) {
if (editTxt.getText().toString().matches("(^([0-9]{0,3})?)(\\.[0-9]{0,1})?$"))
{
regresult.setText("");
}
else
{
regresult.setText("invalid number");
}
}
});
}
}