Ограничение после точки в EditText [дубликат]

Этот вопрос, кажется, очень популярен здесь в stackoverflow, поэтому я решил попробовать и дать лучший ответ, чтобы помочь людям, начинающим в мире iOS, как я.

Надеюсь, что этот ответ ясен

Передача данных вперед

Передача данных в контроллер просмотра с другого контроллера. Вы должны использовать этот метод, если хотите передать объект / значение с одного контроллера вида на другой контроллер представления, который вы можете нажать в стек навигации.

В этом примере мы будем иметь ViewControllerA и ViewControllerB

Чтобы передать значение BOOL с ViewControllerA на ViewControllerB, мы сделали бы следующее.

  1. в ViewControllerB.h создать свойство для BOOL
    @property (nonatomic, assign) BOOL isSomethingEnabled;
    
  2. в ViewControllerA вам нужно рассказать об этом ViewControllerB, поэтому используйте
    #import "ViewControllerB.h"
    
    Затем, где вы хотите загрузить представление, например. didSelectRowAtIndex или несколько IBAction вам нужно установить свойство в ViewControllerB, прежде чем вы нажмете его на стек навигатора.
    ViewControllerB *viewControllerB = [[ViewControllerB alloc] initWithNib:@"ViewControllerB" bundle:nil];
    viewControllerB.isSomethingEnabled = YES;
    [self pushViewController:viewControllerB animated:YES];
    
    Это установит isSomethingEnabled в значение ViewControllerB на BOOL значение YES.

Передача данных вперед с помощью Segues

Если вы используете раскадровки вы, скорее всего, используете segues и будете нуждаться в этой процедуре для передачи данных вперед. Это похоже на приведенное выше, но вместо передачи данных перед тем, как вы нажимаете контроллер вида, вы используете метод, называемый

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender

. Итак, чтобы передать BOOL с ViewControllerA на ViewControllerB, мы выполнил бы следующее:

  1. в ViewControllerB.h создать свойство для BOOL
    @property (nonatomic, assign) BOOL isSomethingEnabled;
    
  2. в ViewControllerA, вам нужно рассказать об этом ViewControllerB поэтому используйте
    #import "ViewControllerB.h"
    
  3. Создайте выделение от ViewControllerA до ViewControllerB на раскадровке и дайте ему идентификатор, в этом примере мы будем называть его "showDetailSegue"
  4. Затем нам нужно добавить метод к ViewControllerA, который вызывается, когда выполняется какой-либо segue, из-за этого нам нужно определить, какой вызов был вызван, а затем что-то сделать. В нашем примере мы проверим "showDetailSegue", и если это будет выполнено, мы передадим наше значение BOOL в ViewControllerB
    -(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
        if([segue.identifier isEqualToString:@"showDetailSegue"]){
            ViewControllerB *controller = (ViewControllerB *)segue.destinationViewController;
            controller.isSomethingEnabled = YES;
        }
    }
    
    . Если у вас есть свои представления, встроенные в контроллер навигации, вам нужно немного изменить метод выше на следующие
    -(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
        if([segue.identifier isEqualToString:@"showDetailSegue"]){
            UINavigationController *navController = (UINavigationController *)segue.destinationViewController;
            ViewControllerB *controller = (ViewControllerB *)navController.topViewController;
            controller.isSomethingEnabled = YES;
        }
    }
    
    Это установит isSomethingEnabled в ViewControllerB на значение BOOL YES.

Передача данных Назад

Чтобы передать данные с ViewControllerB ] до ViewControllerA вам нужно использовать Protocols and Delegates или Blocks , последний может использоваться как слабо связанный механизм для обратных вызовов.

To сделаем это, мы сделаем ViewControllerA делегатом из ViewControllerB. Это позволяет ViewControllerB отправить сообщение обратно на ViewControllerA, чтобы мы могли отправить данные назад.

Чтобы ViewControllerA был делегатом ViewControllerB, он должен соответствовать протоколу ViewControllerB, который мы должны указать. Это указывает ViewControllerA, какие методы он должен реализовать.

  1. В ViewControllerB.h ниже #import, но выше @interface вы указываете протокол.
    @class ViewControllerB;
    
    @protocol ViewControllerBDelegate 
    - (void)addItemViewController:(ViewControllerB *)controller didFinishEnteringItem:(NSString *)item;
    @end
    
  2. далее в ViewControllerB.h вам нужно настроить свойство delegate и синтезировать в ViewControllerB.m
    @property (nonatomic, weak) id  delegate;
    
  3. В ViewControllerB мы вызываем сообщение на delegate, когда мы выходим на контроллер вида.
    NSString *itemToPassBack = @"Pass this value back to ViewControllerA";
    [self.delegate addItemViewController:self didFinishEnteringItem:itemToPassBack];
    
  4. Это для ViewControllerB. Теперь в ViewControllerA.h скажите ViewControllerA, чтобы импортировать ViewControllerB и соответствовать его протоколу.
    #import "ViewControllerB.h"
    
    @interface ViewControllerA : UIViewController 
    
  5. В ViewControllerA.m реализуем следующий метод из нашего протокола
    - (void)addItemViewController:(ViewControllerB *)controller didFinishEnteringItem:(NSString *)item
    {
        NSLog(@"This was returned from ViewControllerB %@",item);
    }
    
  6. . Перед нажатием viewControllerB в стек навигации нам нужно сообщить ViewControllerB, что ViewControllerA является его делегатом, иначе мы получим сообщение об ошибке.
    ViewControllerB *viewControllerB = [[ViewControllerB alloc] initWithNib:@"ViewControllerB" bundle:nil];
    viewControllerB.delegate = self
    [[self navigationController] pushViewController:viewControllerB animated:YES];
    

Ссылки

95
задан Michael Currie 31 August 2015 в 21:32
поделиться

27 ответов

Эта реализация InputFilter решает проблему.

import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.method.DigitsKeyListener;

public class MoneyValueFilter extends DigitsKeyListener {
    public MoneyValueFilter() {
        super(false, true);
    }

    private int digits = 2;

    public void setDigits(int d) {
        digits = d;
    }

    @Override
    public CharSequence filter(CharSequence source, int start, int end,
            Spanned dest, int dstart, int dend) {
        CharSequence out = super.filter(source, start, end, dest, dstart, dend);

        // if changed, replace the source
        if (out != null) {
            source = out;
            start = 0;
            end = out.length();
        }

        int len = end - start;

        // if deleting, source is empty
        // and deleting can't break anything
        if (len == 0) {
            return source;
        }

        int dlen = dest.length();

        // Find the position of the decimal .
        for (int i = 0; i < dstart; i++) {
            if (dest.charAt(i) == '.') {
                // being here means, that a number has
                // been inserted after the dot
                // check if the amount of digits is right
                return (dlen-(i+1) + len > digits) ? 
                    "" :
                    new SpannableStringBuilder(source, start, end);
            }
        }

        for (int i = start; i < end; ++i) {
            if (source.charAt(i) == '.') {
                // being here means, dot has been inserted
                // check if the amount of digits is right
                if ((dlen-dend) + (end-(i + 1)) > digits)
                    return "";
                else
                    break;  // return new SpannableStringBuilder(source, start, end);
            }
        }

        // if the dot is after the inserted part,
        // nothing can break
        return new SpannableStringBuilder(source, start, end);
    }
}
27
ответ дан Konstantin Weitz 31 August 2018 в 22:40
поделиться

Я сделал некоторые исправления для решения @Pinhassi. Он обрабатывает некоторые случаи:

1. вы можете перемещать курсор в любом месте

2.minus sign handling

3.digitsbefore = 2 и digitsafter = 4, и вы вводите 12,4545. Затем, если вы хотите удалить «.», Это не позволит.

public class DecimalDigitsInputFilter implements InputFilter {
    private int mDigitsBeforeZero;
    private int mDigitsAfterZero;
    private Pattern mPattern;

    private static final int DIGITS_BEFORE_ZERO_DEFAULT = 100;
    private static final int DIGITS_AFTER_ZERO_DEFAULT = 100;

    public DecimalDigitsInputFilter(Integer digitsBeforeZero, Integer digitsAfterZero) {
    this.mDigitsBeforeZero = (digitsBeforeZero != null ? digitsBeforeZero : DIGITS_BEFORE_ZERO_DEFAULT);
    this.mDigitsAfterZero = (digitsAfterZero != null ? digitsAfterZero : DIGITS_AFTER_ZERO_DEFAULT);
    mPattern = Pattern.compile("-?[0-9]{0," + (mDigitsBeforeZero) + "}+((\\.[0-9]{0," + (mDigitsAfterZero)
        + "})?)||(\\.)?");
    }

    @Override
    public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
    String replacement = source.subSequence(start, end).toString();
    String newVal = dest.subSequence(0, dstart).toString() + replacement
        + dest.subSequence(dend, dest.length()).toString();
    Matcher matcher = mPattern.matcher(newVal);
    if (matcher.matches())
        return null;

    if (TextUtils.isEmpty(source))
        return dest.subSequence(dstart, dend);
    else
        return "";
    }
}
14
ответ дан android_dev 31 August 2018 в 22:40
поделиться

Мне не нравится другое решение, и я создал свой собственный. С помощью этого решения вы не можете ввести больше, чем MAX_BEFORE_POINT, перед точкой, а десятичные значения не могут быть больше MAX_DECIMAL.

Вы просто не можете ввести цифру в избытке, никаких других эффектов! В дополнение, если вы пишете «.». он набирает «0».

  1. Установите EditText в макете, чтобы: android: inputType = "numberDecimal"
  2. Добавить слушателя в ваш onCreate. Если вы хотите изменить число цифр до и после редактирования точки, вызов PerfectDecimal (str, NUMBER_BEFORE_POINT, NUMBER_DECIMALS) здесь установлен в 3 и 2
    EditText targetEditText = (EditText)findViewById(R.id.targetEditTextLayoutId);
    
    targetEditText.addTextChangedListener(new TextWatcher() {
      public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {}
    
      public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {}
    
      public void afterTextChanged(Editable arg0) {
        String str = targetEditText.getText().toString();
        if (str.isEmpty()) return;
        String str2 = PerfectDecimal(str, 3, 2);
    
        if (!str2.equals(str)) {
            targetEditText.setText(str2);
            int pos = targetEditText.getText().length();
            targetEditText.setSelection(pos);
        }
      }
    });
    
  3. Включить этот Funcion:
    public String PerfectDecimal(String str, int MAX_BEFORE_POINT, int MAX_DECIMAL){
      if(str.charAt(0) == '.') str = "0"+str;
      int max = str.length();
    
      String rFinal = "";
      boolean after = false;
      int i = 0, up = 0, decimal = 0; char t;
      while(i < max){
        t = str.charAt(i);
        if(t != '.' && after == false){
            up++;
            if(up > MAX_BEFORE_POINT) return rFinal;
        }else if(t == '.'){
            after = true;
        }else{
            decimal++;
            if(decimal > MAX_DECIMAL)
                return rFinal;
        }
        rFinal = rFinal + t;
        i++;
      }return rFinal;
    }
    

И все сделано!

7
ответ дан Apoleo 31 August 2018 в 22:40
поделиться
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
    String numero = total.getText().toString();
    int dec = numero.indexOf(".");
    int longitud = numero.length();
    if (dec+3 == longitud && dec != -1) { //3 number decimal + 1
        log.i("ento","si");
        numero = numero.substring(0,dec+3);
        if (contador == 0) {
            contador = 1;
            total.setText(numero);
            total.setSelection(numero.length());
        } else {
            contador = 0;
        }
    }
}
1
ответ дан Cody Gray 31 August 2018 в 22:40
поделиться

Мне очень понравился ответ Пинхасси, но заметил, что после того, как пользователь ввел указанные цифры числа после десятичной точки, вы больше не могли вводить текст в левую часть десятичной точки. Проблема заключалась в том, что решение только тестировало предыдущий текст, который был введен, а не текущий текст. Итак, вот мое решение, которое вставляет новый символ в исходный текст для проверки.

package com.test.test;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import android.text.InputFilter;
import android.text.Spanned;
import android.util.Log;

public class InputFilterCurrency implements InputFilter {
    Pattern moPattern;

    public InputFilterCurrency(int aiMinorUnits) {
        // http://www.regexplanet.com/advanced/java/index.html
        moPattern=Pattern.compile("[0-9]*+((\\.[0-9]{0,"+ aiMinorUnits + "})?)||(\\.)?");

    } // InputFilterCurrency

    @Override
    public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
        String lsStart  = "";
        String lsInsert = "";
        String lsEnd    = "";
        String lsText   = "";

        Log.d("debug", moPattern.toString());
        Log.d("debug", "source: " + source + ", start: " + start + ", end:" + end + ", dest: " + dest + ", dstart: " + dstart + ", dend: " + dend );

        lsText = dest.toString();

        // If the length is greater then 0, then insert the new character
        // into the original text for validation
        if (lsText.length() > 0) {

            lsStart = lsText.substring(0, dstart);
            Log.d("debug", "lsStart : " + lsStart);
            // Check to see if they have deleted a character
            if (source != "") {
                lsInsert = source.toString();
                Log.d("debug", "lsInsert: " + lsInsert);
            } // if
            lsEnd = lsText.substring(dend);
            Log.d("debug", "lsEnd   : " + lsEnd);
            lsText = lsStart + lsInsert + lsEnd;
            Log.d("debug", "lsText  : " + lsText);

        } // if

        Matcher loMatcher = moPattern.matcher(lsText);
        Log.d("debug", "loMatcher.matches(): " + loMatcher.matches() + ", lsText: " + lsText);
        if(!loMatcher.matches()) {
            return "";
        }
        return null;

    } // CharSequence

} // InputFilterCurrency

И вызов для установки фильтра editText

editText.setFilters(new InputFilter[] {new InputFilterCurrency(2)});

Ouput with two decimal places
05-22 15:25:33.434: D/debug(30524): [0-9]*+((\.[0-9]{0,2})?)||(\.)?
05-22 15:25:33.434: D/debug(30524): source: 5, start: 0, end:1, dest: 123.4, dstart: 5, dend: 5
05-22 15:25:33.434: D/debug(30524): lsStart : 123.4
05-22 15:25:33.434: D/debug(30524): lsInsert: 5
05-22 15:25:33.434: D/debug(30524): lsEnd   : 
05-22 15:25:33.434: D/debug(30524): lsText  : 123.45
05-22 15:25:33.434: D/debug(30524): loMatcher.matches(): true, lsText: 123.45

Ouput inserting a 5 in the middle
05-22 15:26:17.624: D/debug(30524): [0-9]*+((\.[0-9]{0,2})?)||(\.)?
05-22 15:26:17.624: D/debug(30524): source: 5, start: 0, end:1, dest: 123.45, dstart: 2, dend: 2
05-22 15:26:17.624: D/debug(30524): lsStart : 12
05-22 15:26:17.624: D/debug(30524): lsInsert: 5
05-22 15:26:17.624: D/debug(30524): lsEnd   : 3.45
05-22 15:26:17.624: D/debug(30524): lsText  : 1253.45
05-22 15:26:17.624: D/debug(30524): loMatcher.matches(): true, lsText: 1253.45
1
ответ дан David Murry 31 August 2018 в 22:40
поделиться

Мое решение прост и прекрасно работает!

public class DecimalInputTextWatcher implements TextWatcher {

private String mPreviousValue;
private int mCursorPosition;
private boolean mRestoringPreviousValueFlag;
private int mDigitsAfterZero;
private EditText mEditText;

public DecimalInputTextWatcher(EditText editText, int digitsAfterZero) {
    mDigitsAfterZero = digitsAfterZero;
    mEditText = editText;
    mPreviousValue = "";
    mRestoringPreviousValueFlag = false;
}

@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
    if (!mRestoringPreviousValueFlag) {
        mPreviousValue = s.toString();
        mCursorPosition = mEditText.getSelectionStart();
    }
}

@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}

@Override
public void afterTextChanged(Editable s) {
    if (!mRestoringPreviousValueFlag) {

        if (!isValid(s.toString())) {
            mRestoringPreviousValueFlag = true;
            restorePreviousValue();
        }

    } else {
        mRestoringPreviousValueFlag = false;
    }
}

private void restorePreviousValue() {
    mEditText.setText(mPreviousValue);
    mEditText.setSelection(mCursorPosition);
}

private boolean isValid(String s) {
    Pattern patternWithDot = Pattern.compile("[0-9]*((\\.[0-9]{0," + mDigitsAfterZero + "})?)||(\\.)?");
    Pattern patternWithComma = Pattern.compile("[0-9]*((,[0-9]{0," + mDigitsAfterZero + "})?)||(,)?");

    Matcher matcherDot = patternWithDot.matcher(s);
    Matcher matcherComa = patternWithComma.matcher(s);

    return matcherDot.matches() || matcherComa.matches();
}
}

Использование:

myTextEdit.addTextChangedListener(new DecimalInputTextWatcher(myTextEdit, 2));
10
ответ дан Dominik Suszczewicz 31 August 2018 в 22:40
поделиться

Вот пример InputFilter, который позволяет довести до 4 цифр до десятичной точки и максимум 1 цифру.

Значения, которые edittext позволяет: 555.2, 555, .2

Значения, которые выделяют блоки: 55555.2, 055.2, 555.42

        InputFilter filter = new InputFilter() {
        final int maxDigitsBeforeDecimalPoint=4;
        final int maxDigitsAfterDecimalPoint=1;

        @Override
        public CharSequence filter(CharSequence source, int start, int end,
                Spanned dest, int dstart, int dend) {
                StringBuilder builder = new StringBuilder(dest);
                builder.replace(dstart, dend, source
                        .subSequence(start, end).toString());
                if (!builder.toString().matches(
                        "(([1-9]{1})([0-9]{0,"+(maxDigitsBeforeDecimalPoint-1)+"})?)?(\\.[0-9]{0,"+maxDigitsAfterDecimalPoint+"})?"

                        )) {
                    if(source.length()==0)
                        return dest.subSequence(dstart, dend);
                    return "";
                }

            return null;

        }
    };

    mEdittext.setFilters(new InputFilter[] { filter });
25
ответ дан Favas Kv 31 August 2018 в 22:40
поделиться

Я достиг этого с помощью TextWatcher следующим образом

final EditText et = (EditText) findViewById(R.id.EditText1);
et.addTextChangedListener(new TextWatcher() {
    public void onTextChanged(CharSequence arg0, int arg1, int arg2,int arg3) {             

    }
    public void beforeTextChanged(CharSequence arg0, int arg1,int arg2, int arg3) {             

    }

    public void afterTextChanged(Editable arg0) {
        if (arg0.length() > 0) {
            String str = et.getText().toString();
            et.setOnKeyListener(new OnKeyListener() {
                public boolean onKey(View v, int keyCode, KeyEvent event) {
                    if (keyCode == KeyEvent.KEYCODE_DEL) {
                        count--;
                        InputFilter[] fArray = new InputFilter[1];
                        fArray[0] = new InputFilter.LengthFilter(100);
                        et.setFilters(fArray);
                        //change the edittext's maximum length to 100. 
                        //If we didn't change this the edittext's maximum length will
                        //be number of digits we previously entered.
                    }
                    return false;
                }
            });
            char t = str.charAt(arg0.length() - 1);
            if (t == '.') {
                count = 0;
            }
            if (count >= 0) {
                if (count == 2) {                        
                    InputFilter[] fArray = new InputFilter[1];
                    fArray[0] = new InputFilter.LengthFilter(arg0.length());
                    et.setFilters(fArray);
                    //prevent the edittext from accessing digits 
                    //by setting maximum length as total number of digits we typed till now.
                }
                count++;
            }
        }
    }
});

Это решение не позволит пользователю вводить более двух цифр после десятичной точки. Также вы можете ввести любое количество цифр до десятичной точки. Посмотрите этот блог http://v4all123.blogspot.com/2013/05/set-limit-for-fraction-in-decimal.html , чтобы установить фильтр для нескольких EditText. Я надеюсь, это поможет. Спасибо.

17
ответ дан Gunaseelan 31 August 2018 в 22:40
поделиться
DecimalFormat form = new DecimalFormat("#.##", new DecimalFormatSymbols(Locale.US));
    EditText et; 
    et.setOnEditorActionListener(new TextView.OnEditorActionListener() {
        @Override
        public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {

        if (actionId == EditorInfo.IME_ACTION_DONE) {
            double a = Double.parseDouble(et.getText().toString());
            et.setText(form.format(a));
        }
        return false;
    }
});

Что происходит, когда вы покидаете этап редактирования, он форматирует поле в нужном формате. В этот момент у него есть только 2 десятичных символа. Я думаю, что это довольно простой способ сделать это.

2
ответ дан Jake1164 31 August 2018 в 22:40
поделиться

Вот мое решение:

     yourEditText.addTextChangedListener(new TextWatcher() {
        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            NumberFormat formatter = new DecimalFormat("#.##");
            double doubleVal = Double.parseDouble(s.toString());
            yourEditText.setText(formatter.format(doubleVal));
        }

        @Override
        public void beforeTextChanged(CharSequence s, int start, int count,int after) {}

        @Override
        public void afterTextChanged(Editable s) {}
    });

Если пользователь вводит число с более чем двумя числами после десятичной точки, оно будет автоматически исправлено.

Надеюсь, что я помогли!

0
ответ дан lopez.mikhael 31 August 2018 в 22:40
поделиться

В появившемся окне InputFilter вы можете настроить количество цифр до и после десятичного разряда. Кроме того, он запрещает начало нулей.

public class DecimalDigitsInputFilter implements InputFilter
{
    Pattern pattern;

    public DecimalDigitsInputFilter(int digitsBeforeDecimal, int digitsAfterDecimal)
    {
        pattern = Pattern.compile("(([1-9]{1}[0-9]{0," + (digitsBeforeDecimal - 1) + "})?||[0]{1})((\\.[0-9]{0," + digitsAfterDecimal + "})?)||(\\.)?");
    }

    @Override public CharSequence filter(CharSequence source, int sourceStart, int sourceEnd, Spanned destination, int destinationStart, int destinationEnd)
    {
        // Remove the string out of destination that is to be replaced.
        String newString = destination.toString().substring(0, destinationStart) + destination.toString().substring(destinationEnd, destination.toString().length());

        // Add the new string in.
        newString = newString.substring(0, destinationStart) + source.toString() + newString.substring(destinationStart, newString.length());

        // Now check if the new string is valid.
        Matcher matcher = pattern.matcher(newString);

        if(matcher.matches())
        {
            // Returning null indicates that the input is valid.
            return null;
        }

        // Returning the empty string indicates the input is invalid.
        return "";
    }
}

// To use this InputFilter, attach it to your EditText like so:
final EditText editText = (EditText) findViewById(R.id.editText);

EditText.setFilters(new InputFilter[]{new DecimalDigitsInputFilter(4, 4)});
6
ответ дан Luke 31 August 2018 в 22:40
поделиться

Требование - 2 цифры после десятичной. Не должно быть предела для цифр до десятичной точки. Итак, решение должно быть,

public class DecimalDigitsInputFilter implements InputFilter {

    Pattern mPattern;

    public DecimalDigitsInputFilter() {
        mPattern = Pattern.compile("[0-9]*+((\\.[0-9]?)?)||(\\.)?");
    }

    @Override
    public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
        Matcher matcher = mPattern.matcher(dest);
        if (!matcher.matches())
            return "";
        return null;
    }
}

И использовать его как

mEditText.setFilters(new InputFilter[]{new DecimalDigitsInputFilter()});

Благодаря @Pinhassi для вдохновения.

5
ответ дан Mangesh 31 August 2018 в 22:40
поделиться

Попробуйте использовать NumberFormat.getCurrencyInstance () , чтобы форматировать вашу строку, прежде чем помещать ее в текстовый файл.

Что-то вроде:

NumberFormat currency = NumberFormat.getCurrencyInstance();
myTextView.setText(currency.format(dollars));

Редактировать - Нет типа inputType для валюты, который я мог бы найти в документах. Я предполагаю, что это связано с тем, что существуют некоторые валюты, которые не соответствуют тому же правилу для десятичных знаков, таких как японская иена.

Как упоминал LeffelMania, вы можете исправить ввод пользователя, используя приведенный выше код с TextWatcher, который установлен на вашем EditText.

5
ответ дан Matthew Willis 31 August 2018 в 22:40
поделиться

Все ответы здесь довольно сложны. Я старался сделать это намного проще. Посмотрите на мой код и решите для себя -

int temp  = 0;
int check = 0;

editText.addTextChangedListener(new TextWatcher() {

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {

        if(editText.getText().toString().length()<temp)
        {
            if(!editText.getText().toString().contains("."))
                editText.setFilters(new InputFilter[] { new InputFilter.LengthFilter(editText.getText().toString().length()-1) });
            else
                editText.setFilters(new InputFilter[] { new InputFilter.LengthFilter(editText.getText().toString().length()+1) });

        }

        if(!editText.getText().toString().contains("."))
        {
            editText.setFilters(new InputFilter[] { new InputFilter.LengthFilter(editText.getText().toString().length()+1) });
            check=0;
        }


        else if(check==0)
        {
            check=1;
            editText.setFilters(new InputFilter[] { new InputFilter.LengthFilter(editText.getText().toString().length()+2) });
        }
    }

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count,
            int after) {
        temp = editText.getText().toString().length();


    }

    @Override
    public void afterTextChanged(Editable s) {
        // TODO Auto-generated method stub

    }
});
3
ответ дан mjosh 31 August 2018 в 22:40
поделиться

Очень поздний ответ: мы можем сделать это просто так:

etv.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) {
            if (s.toString().length() > 3 && s.toString().contains(".")) {
                if (s.toString().length() - s.toString().indexOf(".") > 3) {
                    etv.setText(s.toString().substring(0, s.length() - 1));
                    etv.setSelection(edtSendMoney.getText().length());
                }
            }
        }

        @Override
        public void afterTextChanged(Editable arg0) {
        }
}
1
ответ дан NanPd 31 August 2018 в 22:40
поделиться

Упрощенное решение без использования регулярного выражения:

import android.text.InputFilter;
import android.text.Spanned;

/**
 * Input filter that limits the number of decimal digits that are allowed to be
 * entered.
 */
public class DecimalDigitsInputFilter implements InputFilter {

  private final int decimalDigits;

  /**
   * Constructor.
   * 
   * @param decimalDigits maximum decimal digits
   */
  public DecimalDigitsInputFilter(int decimalDigits) {
    this.decimalDigits = decimalDigits;
  }

  @Override
  public CharSequence filter(CharSequence source,
      int start,
      int end,
      Spanned dest,
      int dstart,
      int dend) {


    int dotPos = -1;
    int len = dest.length();
    for (int i = 0; i < len; i++) {
      char c = dest.charAt(i);
      if (c == '.' || c == ',') {
        dotPos = i;
        break;
      }
    }
    if (dotPos >= 0) {

      // protects against many dots
      if (source.equals(".") || source.equals(","))
      {
          return "";
      }
      // if the text is entered before the dot
      if (dend <= dotPos) {
        return null;
      }
      if (len - dotPos > decimalDigits) {
        return "";
      }
    }

    return null;
  }

}

Для использования:

editText.setFilters(new InputFilter[] {new DecimalDigitsInputFilter(2)});
52
ответ дан peceps 31 August 2018 в 22:40
поделиться

Слегка улучшенное решение @Pinhassi.

Работает очень хорошо. Он проверяет конкатенированные строки.

public class DecimalDigitsInputFilter implements InputFilter {

Pattern mPattern;

public DecimalDigitsInputFilter() {
    mPattern = Pattern.compile("([1-9]{1}[0-9]{0,2}([0-9]{3})*(\\.[0-9]{0,2})?|[1-9]{1}[0-9]{0,}(\\.[0-9]{0,2})?|0(\\.[0-9]{0,2})?|(\\.[0-9]{1,2})?)");

}

@Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {

    String formatedSource = source.subSequence(start, end).toString();

    String destPrefix = dest.subSequence(0, dstart).toString();

    String destSuffix = dest.subSequence(dend, dest.length()).toString();

    String result = destPrefix + formatedSource + destSuffix;

    result = result.replace(",", ".");

    Matcher matcher = mPattern.matcher(result);

    if (matcher.matches()) {
        return null;
    }

    return "";
}

 }
95
ответ дан pixel 31 August 2018 в 22:40
поделиться

@Meh для u ..

txtlist.setFilters(new InputFilter[] { new DigitsKeyListener( Boolean.FALSE,Boolean.TRUE) {

        int beforeDecimal = 7;
        int afterDecimal = 2;

        @Override
        public CharSequence filter(CharSequence source, int start, int end,Spanned dest, int dstart, int dend) {

            String etText = txtlist.getText().toString();
            String temp = txtlist.getText() + source.toString();
            if (temp.equals(".")) {
                return "0.";
            } else if (temp.toString().indexOf(".") == -1) {
                // no decimal point placed yet
                 if (temp.length() > beforeDecimal) {
                    return "";
                }
            } else {
                int dotPosition ;
                int cursorPositon = txtlistprice.getSelectionStart();
                if (etText.indexOf(".") == -1) {
                    dotPosition = temp.indexOf(".");
                }else{
                    dotPosition = etText.indexOf(".");
                }
                if(cursorPositon <= dotPosition){
                    String beforeDot = etText.substring(0, dotPosition);
                    if(beforeDot.length()<beforeDecimal){
                        return source;
                    }else{
                        if(source.toString().equalsIgnoreCase(".")){
                            return source;
                        }else{
                            return "";
                        }
                    }
                }else{
                    temp = temp.substring(temp.indexOf(".") + 1);
                    if (temp.length() > afterDecimal) {
                        return "";
                    }
                }
            }
            return super.filter(source, start, end, dest, dstart, dend);
        }
    } });
1
ответ дан RaRa 31 August 2018 в 22:40
поделиться

Как и другие, я добавил этот класс в свой проект и установил фильтр в EditText, который я хочу.

Фильтр копируется из ответа @ Pixel. Я просто собираю все это вместе.

public class DecimalDigitsInputFilter implements InputFilter {

    Pattern mPattern;

    public DecimalDigitsInputFilter() {
        mPattern = Pattern.compile("([1-9]{1}[0-9]{0,2}([0-9]{3})*(\\.[0-9]{0,2})?|[1-9]{1}[0-9]{0,}(\\.[0-9]{0,2})?|0(\\.[0-9]{0,2})?|(\\.[0-9]{1,2})?)");

    }

    @Override
    public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {

        String formatedSource = source.subSequence(start, end).toString();

        String destPrefix = dest.subSequence(0, dstart).toString();

        String destSuffix = dest.subSequence(dend, dest.length()).toString();

        String result = destPrefix + formatedSource + destSuffix;

        result = result.replace(",", ".");

        Matcher matcher = mPattern.matcher(result);

        if (matcher.matches()) {
            return null;
        }

        return "";
    }
}

Теперь установите фильтр в ваш EditText, как это.

mEditText.setFilters(new InputFilter[]{new DecimalDigitsInputFilter()});

Здесь важна то, что он решает мою проблему, не позволяя показывать более двух цифр после десятичной точки в EditText, но проблема в том, что когда I getText() из этого EditText, он возвращает весь введенный мной ввод.

Например, после применения фильтра по EditText я попытался установить вход 1,5699856987. Таким образом, на экране это показывает 1.56, что идеально.

Затем я хотел использовать этот ввод для некоторых других вычислений, поэтому я хотел получить текст из этого поля ввода (EditText). Когда я позвонил mEditText.getText().toString(), он возвращает 1.5699856987, что было неприемлемо в моем случае.

Поэтому мне пришлось снова проанализировать значение после получения его из EditText.

BigDecimal amount = new BigDecimal(Double.parseDouble(mEditText.getText().toString().trim()))
    .setScale(2, RoundingMode.HALF_UP);

setScale делает трюк здесь после получения полного текста из EditText.

1
ответ дан Reaz Murshed 31 August 2018 в 22:40
поделиться

Я улучшил решение, которое использует регулярное выражение для Pinhassi, поэтому оно также правильно обрабатывает края. Прежде чем проверять правильность ввода, сначала окончательная строка построена, как описано в документах android.

public class DecimalDigitsInputFilter implements InputFilter {

    private Pattern mPattern;

    private static final Pattern mFormatPattern = Pattern.compile("\\d+\\.\\d+");

    public DecimalDigitsInputFilter(int digitsBeforeDecimal, int digitsAfterDecimal) {
        mPattern = Pattern.compile(
            "^\\d{0," + digitsBeforeDecimal + "}([\\.,](\\d{0," + digitsAfterDecimal +
                "})?)?$");
    }

    @Override
    public CharSequence filter(CharSequence source, int start, int end, Spanned dest, 
                               int dstart, int dend) {

        String newString =
            dest.toString().substring(0, dstart) + source.toString().substring(start, end) 
            + dest.toString().substring(dend, dest.toString().length());

        Matcher matcher = mPattern.matcher(newString);
        if (!matcher.matches()) {
            return "";
        }
        return null;
    }
}

Использование:

editText.setFilters(new InputFilter[] {new DecimalDigitsInputFilter(5,2)});
1
ответ дан reisub 31 August 2018 в 22:40
поделиться

Это должно основываться на ответе pinhassi - проблема, с которой я столкнулся, заключалась в том, что вы не могли добавлять значения до десятичного знака после достижения десятичного предела. Чтобы исправить проблему, нам нужно построить финальную строку перед выполнением соответствия шаблону.

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import android.text.InputFilter;
import android.text.Spanned;

public class DecimalLimiter implements InputFilter
{
    Pattern mPattern;

    public DecimalLimiter(int digitsBeforeZero,int digitsAfterZero) 
    {
        mPattern=Pattern.compile("[0-9]{0," + (digitsBeforeZero) + "}+((\\.[0-9]{0," + (digitsAfterZero) + "})?)||(\\.)?");
    }

    @Override
    public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) 
    {
        StringBuilder sb = new StringBuilder(dest);
        sb.insert(dstart, source, start, end);

        Matcher matcher = mPattern.matcher(sb.toString());
        if(!matcher.matches())
            return "";
        return null;
    }
}
0
ответ дан Robert Conley 31 August 2018 в 22:40
поделиться

Класс Simple Helper предназначен для предотвращения ввода пользователем более двух цифр после десятичной:

public class CostFormatter  implements TextWatcher {

private final EditText costEditText;

public CostFormatter(EditText costEditText) {
    this.costEditText = costEditText;
}

@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 synchronized void afterTextChanged(final Editable text) {
    String cost = text.toString().trim();

    if(!cost.endsWith(".") && cost.contains(".")){
        String numberBeforeDecimal = cost.split("\\.")[0];
        String numberAfterDecimal = cost.split("\\.")[1];

        if(numberAfterDecimal.length() > 2){
            numberAfterDecimal = numberAfterDecimal.substring(0, 2);
        }
        cost = numberBeforeDecimal + "." + numberAfterDecimal;
    }
    costEditText.removeTextChangedListener(this);
    costEditText.setText(cost);
    costEditText.setSelection(costEditText.getText().toString().trim().length());
    costEditText.addTextChangedListener(this);
}
}
2
ответ дан Santhosh 31 August 2018 в 22:40
поделиться

Это отлично работает для меня. Он позволяет вводить значение даже после того, как фокус изменен и восстановлен обратно. Например: 123.00, 12.12, 0.01 и т. Д.

1. Integer.parseInt(getString(R.string.valuelength)) Определяет длину входа digits.Values, доступ к которому получен из файла string.xml. для изменения значений. 2. Integer.parseInt(getString(R.string.valuedecimal)), это максимальный предел десятичных мест.

private InputFilter[] valDecimalPlaces;
private ArrayList<EditText> edittextArray;

valDecimalPlaces = new InputFilter[] { new DecimalDigitsInputFilterNew(
    Integer.parseInt(getString(R.string.valuelength)),
    Integer.parseInt(getString(R.string.valuedecimal))) 
};

Массив значений EditText, который позволяет выполнять действие.

for (EditText etDecimalPlace : edittextArray) {
            etDecimalPlace.setFilters(valDecimalPlaces);

Я просто использовал массив значений, которые содержат несколько файлов edittext Next DecimalDigitsInputFilterNew.class.

import android.text.InputFilter;
import android.text.Spanned;

public class DecimalDigitsInputFilterNew implements InputFilter {

    private final int decimalDigits;
    private final int before;

    public DecimalDigitsInputFilterNew(int before ,int decimalDigits) {
        this.decimalDigits = decimalDigits;
        this.before = before;
    }

    @Override
    public CharSequence filter(CharSequence source, int start, int end,
        Spanned dest, int dstart, int dend) {
        StringBuilder builder = new StringBuilder(dest);
        builder.replace(dstart, dend, source
              .subSequence(start, end).toString());
        if (!builder.toString().matches("(([0-9]{1})([0-9]{0,"+(before-1)+"})?)?(\\.[0-9]{0,"+decimalDigits+"})?")) {
             if(source.length()==0)
                  return dest.subSequence(dstart, dend);
             return "";
        }
        return null;
    }
}
0
ответ дан Schemetrical 31 August 2018 в 22:40
поделиться

Я изменил приведенные выше решения и создал следующий. Вы можете установить количество цифр до и после десятичной точки.

public class DecimalDigitsInputFilter implements InputFilter {

private final Pattern mPattern;

public DecimalDigitsInputFilter(int digitsBeforeZero, int digitsAfterZero) {
    mPattern = Pattern.compile(String.format("[0-9]{0,%d}(\\.[0-9]{0,%d})?", digitsBeforeZero, digitsAfterZero));
}

@Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
    Matcher matcher = mPattern.matcher(createResultString(source, start, end, dest, dstart, dend));
    if (!matcher.matches())
        return "";
    return null;
}

private String createResultString(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
    String sourceString = source.toString();
    String destString = dest.toString();
    return destString.substring(0, dstart) + sourceString.substring(start, end) + destString.substring(dend);
}

}

3
ответ дан tmorcinek 31 August 2018 в 22:40
поделиться

Я также столкнулся с этой проблемой. Я хотел иметь возможность повторно использовать код во многих EditTexts. Это мое решение:

Использование:

CurrencyFormat watcher = new CurrencyFormat();
priceEditText.addTextChangedListener(watcher);

Класс:

public static class CurrencyFormat implements TextWatcher {

    public void onTextChanged(CharSequence arg0, int start, int arg2,int arg3) {}

    public void beforeTextChanged(CharSequence arg0, int start,int arg2, int arg3) {}

    public void afterTextChanged(Editable arg0) {
        int length = arg0.length();
        if(length>0){
            if(nrOfDecimal(arg0.toString())>2)
                    arg0.delete(length-1, length);
        }

    }


    private int nrOfDecimal(String nr){
        int len = nr.length();
        int pos = len;
        for(int i=0 ; i<len; i++){
            if(nr.charAt(i)=='.'){
                pos=i+1;
                    break;
            }
        }
        return len-pos;
    }
}
1
ответ дан Tom 31 August 2018 в 22:40
поделиться

Самый простой способ добиться этого:

et.addTextChangedListener(new TextWatcher() {
    public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
        String text = arg0.toString();
        if (text.contains(".") && text.substring(text.indexOf(".") + 1).length() > 2) {
            et.setText(text.substring(0, text.length() - 1));
            et.setSelection(et.getText().length());
        }
    }

    public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {

    }

    public void afterTextChanged(Editable arg0) {
    }
});
1
ответ дан Cody Gray 31 August 2018 в 22:40
поделиться

Более элегантный способ будет использовать регулярное выражение (regex) следующим образом:

public class DecimalDigitsInputFilter implements InputFilter {

Pattern mPattern;

public DecimalDigitsInputFilter(int digitsBeforeZero,int digitsAfterZero) {
    mPattern=Pattern.compile("[0-9]{0," + (digitsBeforeZero-1) + "}+((\\.[0-9]{0," + (digitsAfterZero-1) + "})?)||(\\.)?");
}

@Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {

        Matcher matcher=mPattern.matcher(dest);       
        if(!matcher.matches())
            return "";
        return null;
    }

}

Чтобы использовать его:

editText.setFilters(new InputFilter[] {new DecimalDigitsInputFilter(5,2)});
95
ответ дан pixel 31 August 2018 в 22:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: