136
<EditText 
    android:id="@+id/editText2" 
    android:layout_height="wrap_content" 
    android:layout_width="fill_parent" 
    android:maxLines="5" 
    android:lines="5">
</EditText>

User can input more than 5 lines, by pressing enter/next row key. How can I limit user input to fixed amount of rows with EditText?

woodshy
  • 4,007
  • 3
  • 19
  • 20
Indrek Kõue
  • 6,068
  • 7
  • 32
  • 66
  • see this post : http://stackoverflow.com/questions/14672234/android-how-to-make-text-in-an-edittext-exactly-fixed-lines/20120343#20120343 – ali safaei Jan 09 '14 at 04:31

20 Answers20

267
<EditText
    android:id="@+id/edit_text"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:inputType="text"
    android:maxLines="1" 
/>

You just need to make sure you have the attribute "inputType" set. It doesn't work without this line.

android:inputType="text"
Noel Chew
  • 3,453
  • 2
  • 11
  • 15
88

The attribute maxLines corresponds to the maximum height of the EditText, it controls the outer boundaries and not inner text lines.

Cedekasme
  • 1,867
  • 1
  • 15
  • 16
  • Thats what I thought also... Is there a way to limit the inputed lines or do I have to it on backend code programmatically? – Indrek Kõue Aug 17 '11 at 14:12
  • There is no simple way to limit the inputed lines like you want. You'll have to do it manually in your code. – Cedekasme Aug 17 '11 at 14:18
  • 3
    I think to a developer "maxLines" implies the maximum number of lines that should be possible with an editText. If I just wanted a specific height I'd use "lines". :-/ – Someone Somewhere Apr 29 '14 at 19:03
71

This does not solve the general issue of limiting to n lines. If you want to limit your EditText to take just 1 line of text, this can be very easy.
You can set this in the xml file.

android:singleLine="true"

or programmatically

editText.setSingleLine(true);
Jesse Black
  • 7,898
  • 3
  • 31
  • 45
  • 10
    but what if you want to limit to 2 rows? or 3? For that you have to build custom row limiter... – Indrek Kõue Nov 20 '11 at 16:29
  • 4
    I am aware of that. "This does not solve the general issue of limiting to n lines". I ended up reading through the question here while I was trying to limit to 1 line and found an easier solution. I figured others might end up here looking to limit their EditText to 1 line and implement the "custom row limiter". My answer is here for other SO users who end up searching this question for the same reason I did. – Jesse Black Nov 20 '11 at 17:57
  • @IndrekKõue that shouldn't be too hard. – Don Larynx May 15 '15 at 00:26
  • 11
    singleLine is deprecated – Ali Apr 30 '17 at 00:56
  • 1
    editText's attribute singleLine = "true" is deprecated and It's going to crash at Devices are using at Android bigger than 7.0 – TranHieu Jan 10 '18 at 02:50
  • For some strange reason, Google decided to deprecate this intuitive attribute. It made more sense than setting maxLines and setting inputType. I am even surprise I don't have to write bajilion hack codes to have a single line edit text. – Neon Warge Jun 28 '18 at 02:34
  • There is no deprecation warning in the docs: https://developer.android.com/reference/android/widget/TextView.html#setSingleLine() – OneWorld Nov 28 '19 at 13:21
24

@Cedekasem you are right, there isn't a built in "row limiter". But I did built one my self, so if anyone is interested the code is below. Cheers.

et.setOnKeyListener(new View.OnKeyListener() {

        @Override
        public boolean onKey(View v, int keyCode, KeyEvent event) {

            // if enter is pressed start calculating
            if (keyCode == KeyEvent.KEYCODE_ENTER
                    && event.getAction() == KeyEvent.ACTION_UP) {

                // get EditText text
                String text = ((EditText) v).getText().toString();

                // find how many rows it cointains
                int editTextRowCount = text.split("\\n").length;

                // user has input more than limited - lets do something
                // about that
                if (editTextRowCount >= 7) {

                    // find the last break
                    int lastBreakIndex = text.lastIndexOf("\n");

                    // compose new text
                    String newText = text.substring(0, lastBreakIndex);

                    // add new text - delete old one and append new one
                    // (append because I want the cursor to be at the end)
                    ((EditText) v).setText("");
                    ((EditText) v).append(newText);

                }
            }

            return false;
        }
});
miguel.martin
  • 1,546
  • 10
  • 26
Indrek Kõue
  • 6,068
  • 7
  • 32
  • 66
  • This has an un-intuitive side-effect for the user. e.g. if you have 7 lines in your EditText and then press enter in the middle of it, then you can say bye-bye to the last line of your text. – miguel.martin Feb 01 '16 at 01:40
  • won't work if you paste more than maxlines text to it. So better would be to use addTextChangedListener. – Kuldeep Sakhiya Mar 31 '16 at 13:03
15

I did something like you guys have been looking for. Here's my LimitedEditText class.

Features:

  • you can limit lines count in your LimitedEditText component
  • you can limit characters count in your LimitedEditText component
  • if you exceed the limit of characters or lines somewhere in the middle of text, cursor
    won't bring you to the end - it will stay where have you been.

Im turning off listener, because every call of setText() method would recursively call these 3 callback methods in case when user exceeded characters or lines limit.

Code:

import android.content.Context;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.EditText;
import android.widget.Toast;

/**
* EditText subclass created to enforce limit of the lines number in editable
* text field
*/
public class LimitedEditText extends EditText {

/**
 * Max lines to be present in editable text field
 */
private int maxLines = 1;

/**
 * Max characters to be present in editable text field
 */
private int maxCharacters = 50;

/**
 * application context;
 */
private Context context;

public int getMaxCharacters() {
    return maxCharacters;
}

public void setMaxCharacters(int maxCharacters) {
    this.maxCharacters = maxCharacters;
}

@Override
public int getMaxLines() {
    return maxLines;
}

@Override
public void setMaxLines(int maxLines) {
    this.maxLines = maxLines;
}

public LimitedEditText(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    this.context = context;
}

public LimitedEditText(Context context, AttributeSet attrs) {
    super(context, attrs);
    this.context = context;
}

public LimitedEditText(Context context) {
    super(context);
    this.context = context;
}

@Override
protected void onFinishInflate() {
    super.onFinishInflate();

    TextWatcher watcher = new TextWatcher() {

        private String text;
        private int beforeCursorPosition = 0;

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

        @Override
        public void beforeTextChanged(CharSequence s, int start, int count,
                int after) {
            text = s.toString();
            beforeCursorPosition = start;
        }

        @Override
        public void afterTextChanged(Editable s) {

            /* turning off listener */
            removeTextChangedListener(this);

            /* handling lines limit exceed */
            if (LimitedEditText.this.getLineCount() > maxLines) {
                LimitedEditText.this.setText(text);
                LimitedEditText.this.setSelection(beforeCursorPosition);
            }

            /* handling character limit exceed */
            if (s.toString().length() > maxCharacters) {
                LimitedEditText.this.setText(text);
                LimitedEditText.this.setSelection(beforeCursorPosition);
                Toast.makeText(context, "text too long", Toast.LENGTH_SHORT)
                        .show();
            }

            /* turning on listener */
            addTextChangedListener(this);

        }
    };

    this.addTextChangedListener(watcher);
}

}
likeitlikeit
  • 5,317
  • 4
  • 33
  • 53
bpawlowski
  • 775
  • 1
  • 9
  • 20
  • 2
    This solution is so simple and elegant! Thanks – GuilhE Oct 03 '14 at 09:33
  • I use `beforeCursorPosition = getSelectionStart();` in `afterTextChanged` callback. It works better because when typing `e` after typing `abcd`, the EditText may 'think' you replace `abcd` with `abcde`, because of input method reason. – hanswim Jul 17 '19 at 10:12
  • This is the best solution – Islam Ahmed Nov 20 '20 at 13:11
12

I've made simpler solution for this :D

// set listeners
    txtSpecialRequests.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            lastSpecialRequestsCursorPosition = txtSpecialRequests.getSelectionStart();
        }

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

        }

        @Override
        public void afterTextChanged(Editable s) {
            txtSpecialRequests.removeTextChangedListener(this);

            if (txtSpecialRequests.getLineCount() > 3) {
                txtSpecialRequests.setText(specialRequests);
                txtSpecialRequests.setSelection(lastSpecialRequestsCursorPosition);
            }
            else
                specialRequests = txtSpecialRequests.getText().toString();

            txtSpecialRequests.addTextChangedListener(this);
        }
    });

You can change the value of 3 in txtSpecialRequests.getLineCount() > 3 to your needs.

Oscar Yuandinata
  • 915
  • 1
  • 10
  • 30
6

Here is a InputFilter that limits allowed lines in EditText:

/**
 * Filter for controlling maximum new lines in EditText.
 */
public class MaxLinesInputFilter implements InputFilter {

  private final int mMax;

  public MaxLinesInputFilter(int max) {
    mMax = max;
  }

  public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
    int newLinesToBeAdded = countOccurrences(source.toString(), '\n');
    int newLinesBefore = countOccurrences(dest.toString(), '\n');
    if (newLinesBefore >= mMax - 1 && newLinesToBeAdded > 0) {
      // filter
      return "";
    }

    // do nothing
    return null;
  }

  /**
   * @return the maximum lines enforced by this input filter
   */
  public int getMax() {
    return mMax;
  }

  /**
   * Counts the number occurrences of the given char.
   *
   * @param string the string
   * @param charAppearance the char
   * @return number of occurrences of the char
   */
  public static int countOccurrences(String string, char charAppearance) {
    int count = 0;
    for (int i = 0; i < string.length(); i++) {
      if (string.charAt(i) == charAppearance) {
        count++;
      }
    }
    return count;
  }
}

To add it to EditText:

editText.setFilters(new InputFilter[]{new MaxLinesInputFilter(2)});
peceps
  • 16,533
  • 10
  • 70
  • 77
4

This is what i used in my project:

editText.addTextChangedListener(new TextWatcher() {
    private String text;

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

public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
    text = arg0.toString();
    }

public void afterTextChanged(Editable arg0) {
    int lineCount = editText.getLineCount();
    if(lineCount > numberOfLines){
    editText.setText(text);
    }
}
});

editText.setOnKeyListener(new View.OnKeyListener() {

public boolean onKey(View v, int keyCode, KeyEvent event) {

// if enter is pressed start calculating
    if (keyCode == KeyEvent.KEYCODE_ENTER && event.getAction() == KeyEvent.ACTION_DOWN){    
    int editTextLineCount = ((EditText)v).getLineCount();
    if (editTextLineCount >= numberOfLines)
        return true;
}

return false;
}
});

And it worked in all scenarios

Gabriel Esteban
  • 752
  • 2
  • 9
  • 31
Pirate
  • 513
  • 1
  • 4
  • 14
  • 1
    What context is the TextWatcher needed? The KeyListener was all I needed. – AlanKley Apr 30 '13 at 02:24
  • @AlanKley: We need before and after text changed events to calculate number of lines of editText. As if we keep on entering text and does not press "new line" key then onKey does not fired and the cursor moved to next line automatically. So to track of these kind of lines we need textWatcher. I hope i am able to make you understood. – Pirate Apr 30 '13 at 12:59
  • I see. Thanks for that clarification. – AlanKley Apr 30 '13 at 16:21
  • @AlanKley If you think my answer is useful then please vote for it. – Pirate May 01 '13 at 06:45
  • public void afterTextChanged(Editable arg0) { int lineCount = editText.getLineCount(); if(lineCount > numberOfLines){ editText.setText(text); } } will throw a StackOverflowException... – desgraci Mar 27 '14 at 17:11
  • @desgraci: Did you tested it and it crashed? According to me it will not crash as I have tested it in all scenarios. – Pirate Oct 09 '14 at 04:54
  • Why do you need "setOnKeyListener" ? – android developer Jun 10 '15 at 11:50
  • @android developer: I have to use because when we press enter it will not call any method of TextWatcher. If I dont check for "Enter" key then user will keep on entering enter and it may go beyond the limit. – Pirate Jun 11 '15 at 04:14
  • @Pirate On which Android version and device have you checked? I always got the TextWatcher method to work. Only that I did as this post says: http://stackoverflow.com/a/30703723/878126 – android developer Jun 11 '15 at 22:00
  • @android developer : I guess it was 4.0 or above and device would be Nexus S and exactly I don't remember which device and android version I tested it. you can check one scenario: Hold the enter key for entering multiple new lines. If you are able to get all those events in TextWatcher then you don't need to use OnKeyListener.. – Pirate Jun 17 '15 at 06:38
  • @Pirate Holding the enter key? Doesn't it allow to access a special operation, like emoticons ? Is it possible it was a bug, and at some point it got fixed? – android developer Jun 17 '15 at 14:30
  • @androiddeveloper: Yes ou are right holding the enter key will open special chars to select. Actually I was getting this error in case of Enter key only when I was giving a new line it does not calling any method of textwatcher. May be it has been fixed by android now. – Pirate Jun 24 '15 at 05:47
  • @Pirate How odd if that's the case. Thank you anyway. – android developer Jun 24 '15 at 06:37
  • @Pirate Say, do you know how to handle the max number of lines, when setting the text ? I mean, using "setText(...)" ? – android developer Jun 24 '15 at 06:40
  • Thanks for this. I changed it a bit by making it a custom view thus slightly simplifying the code. But it works a charm. – theblitz Feb 14 '16 at 15:21
4

Simplest solution:

android:maxLines="3"

...

 @Override
public void afterTextChanged(Editable editable) {
    // limit to 3 lines
    if (editText.getLayout().getLineCount() > 3)
        editText.getText().delete(editText.getText().length() - 1, editText.getText().length());
}
landonmutch
  • 105
  • 1
  • 11
4

set editText android:inputType="text"

4
android:inputType="text" (or something different to "none")
android:maxLines="1"  (and this line)
2

this is one approach. Might help someone.

android:lines="1"
android:maxLines="1"
android:inputType="text
mohammed nathar
  • 150
  • 1
  • 10
2

You can limit your text according to your no of lines i say around 37 alphabets in one line

<EditText
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:lines="4"
    android:maxLines="4"
    android:minLines="4"
    android:maxLength="150"
    android:gravity="start"
    android:background="#efeef5"
    android:layout_marginTop="@dimen/pad_10dp"/>
nafees ahmed
  • 594
  • 1
  • 5
  • 17
1

Another way to limit your EditText to one line is the following:

editText2.setTransformationMethod(new SingleLineTransformationMethod());

Note that after applying this transformation method, the enter key creates spaces when pressed. That still satisfies TS' question.

giorgos.nl
  • 2,257
  • 22
  • 32
0

getLineCount() is one option; if you want non-zero values there make sure your view is measured. For soft keyboard onKeyListener won't work so you have to add addTextChangedListener() that will track text changes as you type. As soon as you get enough lines inside its call backs do whatever you want to limit it: delete characters with getText(), setText() or something more fancy. You can even limit the number of characters using a filter.

Another option is to monitor size of the text with getLineBounds(). This will interact with text gravity/paddign so be careful.

Vlad
  • 4,223
  • 1
  • 28
  • 38
0

For limit number of characters we can simply use maxLength property of EditText as it will not allow user to enter more characters.

Pirate
  • 513
  • 1
  • 4
  • 14
0
        <EditText
            android:id="@+id/usrusr"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:gravity="center"
            android:lines="1"
            android:maxLines="1"
            android:inputType="text"
            android:hint="@string/inventory_no" />
Atiar Talukdar
  • 855
  • 10
  • 18
0

Another idea: each time after typing, new text would be saved to a String lastText, only if the number of lines does not exeed the MAX_LINES. If it does, we would set the text of EditText to the last added text (so the changes would be deleted) and notify user to keep it short.

 // Set listener to wishDescriptionEditText in order to limit line number
    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) {
            // If line account is higher than MAX_LINES, set text to lastText
            // and notify user (by Toast)
            if (editText.getLineCount() > MAX_LINES) {
                editText.setText(lastText);
                Toast.makeText(getContext(), "Please keep it short", Toast.LENGTH_LONG).show();
            } else {
                lastText = editText.getText().toString();
            }
        }
    });
Amir Golan
  • 41
  • 1
  • 5
0

This is an extension of Indrek Kõue answer to Kotlin

                input_name.addTextChangedListener(object : TextWatcher {
                override fun afterTextChanged(s: Editable?) {}

                override fun beforeTextChanged(
                    s: CharSequence?,
                    start: Int,
                    count: Int,
                    after: Int
                ) {
                }

                @SuppressLint("SetTextI18n")
                override fun onTextChanged(
                    s: CharSequence?,
                    start: Int,
                    before: Int,
                    count: Int
                ) {
                    val text = (input_name as EditText).text.toString()
                    val editTextRowCount = input_name.lineCount
                    if (editTextRowCount > 15) {
                        val newText = text.substring(0, text.length - 1)
                        input_name.setText("")
                        input_name.append(newText)
                    }
                }
            })
-5

Try using the following combination of attributes of the EditText inside the xml file:

android:singleLine="true"
android:maxLength="22"

Booger
  • 18,137
  • 6
  • 51
  • 64
Ishrak
  • 471
  • 1
  • 6
  • 16