Limit text length of EditText in Android

2019-01-01 01:47发布

问题:

What\'s the best way to limit the text length of an EditText in Android?

Is there a way to do this via xml?

回答1:

Documentation

Example

android:maxLength=\"10\"


回答2:

use an input filter to limit the max length of a text view.

TextView editEntryView = new TextView(...);
InputFilter[] filterArray = new InputFilter[1];
filterArray[0] = new InputFilter.LengthFilter(8);
editEntryView.setFilters(filterArray);


回答3:

EditText editText = new EditText(this);
int maxLength = 3;    
editText.setFilters(new InputFilter[] {new InputFilter.LengthFilter(maxLength)});


回答4:

A note to people who are already using a custom input filter and also want to limit the max length:

When you assign input filters in code all previously set input filters are cleared, including one set with android:maxLength. I found this out when attempting to use a custom input filter to prevent the use of some characters that we don\'t allow in a password field. After setting that filter with setFilters the maxLength was no longer observed. The solution was to set maxLength and my custom filter together programmatically. Something like this:

myEditText.setFilters(new InputFilter[] {
        new PasswordCharFilter(), new InputFilter.LengthFilter(20)
});


回答5:

TextView tv = new TextView(this);
tv.setFilters(new InputFilter[]{ new InputFilter.LengthFilter(250) });


回答6:

For anyone else wondering how to achieve this, here is my extended EditText class EditTextNumeric.

.setMaxLength(int) - sets maximum number of digits

.setMaxValue(int) - limit maximum integer value

.setMin(int) - limit minimum integer value

.getValue() - get integer value

import android.content.Context;
import android.text.InputFilter;
import android.text.InputType;
import android.widget.EditText;

public class EditTextNumeric extends EditText {
    protected int max_value = Integer.MAX_VALUE;
    protected int min_value = Integer.MIN_VALUE;

    // constructor
    public EditTextNumeric(Context context) {
        super(context);
        this.setInputType(InputType.TYPE_CLASS_NUMBER);
    }

    // checks whether the limits are set and corrects them if not within limits
    @Override
    protected void onTextChanged(CharSequence text, int start, int before, int after) {
        if (max_value != Integer.MAX_VALUE) {
            try {
                if (Integer.parseInt(this.getText().toString()) > max_value) {
                    // change value and keep cursor position
                    int selection = this.getSelectionStart();
                    this.setText(String.valueOf(max_value));
                    if (selection >= this.getText().toString().length()) {
                        selection = this.getText().toString().length();
                    }
                    this.setSelection(selection);
                }
            } catch (NumberFormatException exception) {
                super.onTextChanged(text, start, before, after);
            }
        }
        if (min_value != Integer.MIN_VALUE) {
            try {
                if (Integer.parseInt(this.getText().toString()) < min_value) {
                    // change value and keep cursor position
                    int selection = this.getSelectionStart();
                    this.setText(String.valueOf(min_value));
                    if (selection >= this.getText().toString().length()) {
                        selection = this.getText().toString().length();
                    }
                    this.setSelection(selection);
                }
            } catch (NumberFormatException exception) {
                super.onTextChanged(text, start, before, after);
            }
        }
        super.onTextChanged(text, start, before, after);
    }

    // set the max number of digits the user can enter
    public void setMaxLength(int length) {
        InputFilter[] FilterArray = new InputFilter[1];
        FilterArray[0] = new InputFilter.LengthFilter(length);
        this.setFilters(FilterArray);
    }

    // set the maximum integer value the user can enter.
    // if exeeded, input value will become equal to the set limit
    public void setMaxValue(int value) {
        max_value = value;
    }
    // set the minimum integer value the user can enter.
    // if entered value is inferior, input value will become equal to the set limit
    public void setMinValue(int value) {
        min_value = value;
    }

    // returns integer value or 0 if errorous value
    public int getValue() {
        try {
            return Integer.parseInt(this.getText().toString());
        } catch (NumberFormatException exception) {
            return 0;
        }
    }
}

Example usage:

final EditTextNumeric input = new EditTextNumeric(this);
input.setMaxLength(5);
input.setMaxValue(total_pages);
input.setMinValue(1);

All other methods and attributes that apply to EditText, of course work too.



回答7:

Due to goto10\'s observation, I put together the following code to protected against loosing other filters with setting the max length:

/**
 * This sets the maximum length in characters of an EditText view. Since the
 * max length must be done with a filter, this method gets the current
 * filters. If there is already a length filter in the view, it will replace
 * it, otherwise, it will add the max length filter preserving the other
 * 
 * @param view
 * @param length
 */
public static void setMaxLength(EditText view, int length) {
    InputFilter curFilters[];
    InputFilter.LengthFilter lengthFilter;
    int idx;

    lengthFilter = new InputFilter.LengthFilter(length);

    curFilters = view.getFilters();
    if (curFilters != null) {
        for (idx = 0; idx < curFilters.length; idx++) {
            if (curFilters[idx] instanceof InputFilter.LengthFilter) {
                curFilters[idx] = lengthFilter;
                return;
            }
        }

        // since the length filter was not part of the list, but
        // there are filters, then add the length filter
        InputFilter newFilters[] = new InputFilter[curFilters.length + 1];
        System.arraycopy(curFilters, 0, newFilters, 0, curFilters.length);
        newFilters[curFilters.length] = lengthFilter;
        view.setFilters(newFilters);
    } else {
        view.setFilters(new InputFilter[] { lengthFilter });
    }
}


回答8:

//Set Length filter. Restricting to 10 characters only
editText.setFilters(new InputFilter[]{new InputFilter.LengthFilter(MAX_LENGTH)});

//Allowing only upper case characters
editText.setFilters(new InputFilter[]{new InputFilter.AllCaps()});

//Attaching multiple filters
editText.setFilters(new InputFilter[]{new InputFilter.LengthFilter(MAX_LENGTH), new InputFilter.AllCaps()});


回答9:

Another way you can achieve this is by adding the following definition to the XML file:

<EditText
    android:id=\"@+id/input\"
    android:layout_width=\"0dp\"
    android:layout_height=\"wrap_content\"
    android:inputType=\"number\"
    android:maxLength=\"6\"
    android:hint=\"@string/hint_gov\"
    android:layout_weight=\"1\"/>

This will limit the maximum length of the EditText widget to 6 characters.



回答10:

Xml

android:maxLength=\"10\"

Java:

InputFilter[] editFilters = editText.getFilters();
InputFilter[] newFilters = new InputFilter[editFilters.length + 1];
System.arraycopy(editFilters, 0, newFilters, 0, editFilters.length);
newFilters[editFilters.length] = new InputFilter.LengthFilter(maxLength);
editText.setFilters(newFilters);

Kotlin:

editText.filters += InputFilter.LengthFilter(maxLength)


回答11:

I have had this problem and I consider we are missing a well explained way of doing this programmatically without losing the already set filters.

Setting the length in XML:

As the accepted answer states correctly, if you want to define a fixed length to an EditText which you won\'t change further in the future just define in your EditText XML:

android:maxLength=\"10\" 

Setting the length programmatically

To set the length programmatically you will need to set an InputFilter.

Problem for Java is: once you set it all the other filters go away (e.g. maxLines, inputType, etc). To avoid losing previous filters you need to get those previous applied filters, add the maxLength, and set the filters back to the EditText as follow:

InputFilter[] editFilters = editText.getFilters();
InputFilter[] newFilters = new InputFilter[editFilters.length + 1];
System.arraycopy(editFilters, 0, newFilters, 0, editFilters.length);
newFilters[editFilters.length] = new InputFilter.LengthFilter(10); //the desired length
editText.setFilters(newFilters);

Kotlin however made it easier for everyone, you also need to add the filter to the already existing ones but you can achieve that with a simple:

editText.filters += InputFilter.LengthFilter(maxLength)


回答12:

This is a custom EditText Class that allow Length filter to live along with other filters. Thanks to Tim Gallagher\'s Answer (below)

import android.content.Context;
import android.text.InputFilter;
import android.util.AttributeSet;
import android.widget.EditText;


public class EditTextMultiFiltering extends EditText{

    public EditTextMultiFiltering(Context context) {
        super(context);
    }

    public EditTextMultiFiltering(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public EditTextMultiFiltering(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public void setMaxLength(int length) {
        InputFilter curFilters[];
        InputFilter.LengthFilter lengthFilter;
        int idx;

        lengthFilter = new InputFilter.LengthFilter(length);

        curFilters = this.getFilters();
        if (curFilters != null) {
            for (idx = 0; idx < curFilters.length; idx++) {
                if (curFilters[idx] instanceof InputFilter.LengthFilter) {
                    curFilters[idx] = lengthFilter;
                    return;
                }
            }

            // since the length filter was not part of the list, but
            // there are filters, then add the length filter
            InputFilter newFilters[] = new InputFilter[curFilters.length + 1];
            System.arraycopy(curFilters, 0, newFilters, 0, curFilters.length);
            newFilters[curFilters.length] = lengthFilter;
            this.setFilters(newFilters);
        } else {
            this.setFilters(new InputFilter[] { lengthFilter });
        }
    }
}


回答13:

it simple way in xml:

android:maxLength=\"4\"

if u require to set 4 character in xml edit-text so,use this

<EditText
    android:id=\"@+id/edtUserCode\"
    android:layout_width=\"wrap_content\"
    android:layout_height=\"wrap_content\"
    android:maxLength=\"4\"
    android:hint=\"Enter user code\" />


回答14:

This works fine...

android:maxLength=\"10\"

this will accept only 10 characters.



回答15:

I had saw a lot of good solutions, but I\'d like to give a what I think as more complete and user-friendly solution, which include:

1, Limit length.
2, If input more, give a callback to trigger your toast.
3, Cursor can be at middle or tail.
4, User can input by paste a string.
5, Always discard overflow input and keep origin.

public class LimitTextWatcher implements TextWatcher {

    public interface IF_callback{
        void callback(int left);
    }

    public IF_callback if_callback;

    EditText editText;
    int maxLength;

    int cursorPositionLast;
    String textLast;
    boolean bypass;

    public LimitTextWatcher(EditText editText, int maxLength, IF_callback if_callback) {

        this.editText = editText;
        this.maxLength = maxLength;
        this.if_callback = if_callback;
    }

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

        if (bypass) {

            bypass = false;

        } else {

            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append(s);
            textLast = stringBuilder.toString();

            this.cursorPositionLast = editText.getSelectionStart();
        }
    }

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

    }

    @Override
    public void afterTextChanged(Editable s) {
        if (s.toString().length() > maxLength) {

            int left = maxLength - s.toString().length();

            bypass = true;
            s.clear();

            bypass = true;
            s.append(textLast);

            editText.setSelection(this.cursorPositionLast);

            if (if_callback != null) {
                if_callback.callback(left);
            }
        }

    }

}


edit_text.addTextChangedListener(new LimitTextWatcher(edit_text, MAX_LENGTH, new LimitTextWatcher.IF_callback() {
    @Override
    public void callback(int left) {
        if(left <= 0) {
            Toast.makeText(MainActivity.this, \"input is full\", Toast.LENGTH_SHORT).show();
        }
    }
}));

What I failed to do is, if user highlight a part of the current input and try to paste an very long string, I don\'t know how to restore the highlight.

Such as, max length is set to 10, user inputed \'12345678\', and mark \'345\' as highlight, and try to paste a string of \'0000\' which will exceed limitation.

When I try to use edit_text.setSelection(start=2, end=4) to restore origin status, the result is, it just insert 2 space as \'12 345 678\', not the origin highlight. I\'d like someone solve that.



回答16:

You can use android:maxLength=\"10\" in the EditText.(Here the limit is upto 10 characters)