EditText maxLines not working - user can still input more lines than set

AndroidAndroid LayoutAndroid Edittext

Android Problem Overview


<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?

Android Solutions


Solution 1 - Android

<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"

Solution 2 - Android

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

Solution 3 - Android

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);

Solution 4 - Android

@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;
		}
});

Solution 5 - Android

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);
}

}

Solution 6 - Android

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.

Solution 7 - Android

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

Solution 8 - Android

set editText android:inputType="text"

Solution 9 - Android

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)});


Solution 10 - Android

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

Solution 11 - Android

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());
}

Solution 12 - Android

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"/>

Solution 13 - Android

this is one approach. Might help someone.

android:lines="1"
android:maxLines="1"
android:inputType="text

Solution 14 - Android

        <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" />

Solution 15 - Android

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();
            }
        }
    });

Solution 16 - Android

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)
                    }
                }
            })

Solution 17 - Android

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.

Solution 18 - Android

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

Solution 19 - Android

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.

Solution 20 - Android

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

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionIndrek K&#245;ueView Question on Stackoverflow
Solution 1 - AndroidNoel ChewView Answer on Stackoverflow
Solution 2 - AndroidCedekasmeView Answer on Stackoverflow
Solution 3 - AndroidJesse BlackView Answer on Stackoverflow
Solution 4 - AndroidIndrek KõueView Answer on Stackoverflow
Solution 5 - AndroidbpawlowskiView Answer on Stackoverflow
Solution 6 - AndroidOscar YuandinataView Answer on Stackoverflow
Solution 7 - AndroidAdrián PrietoView Answer on Stackoverflow
Solution 8 - AndroidVimal PrabhuView Answer on Stackoverflow
Solution 9 - AndroidpecepsView Answer on Stackoverflow
Solution 10 - AndroidPirateView Answer on Stackoverflow
Solution 11 - AndroidlandonmutchView Answer on Stackoverflow
Solution 12 - Androidnafees ahmedView Answer on Stackoverflow
Solution 13 - Androidmohammed natharView Answer on Stackoverflow
Solution 14 - AndroidAtiar TalukdarView Answer on Stackoverflow
Solution 15 - AndroidAmir GolanView Answer on Stackoverflow
Solution 16 - AndroidКонстантин КазаченкоView Answer on Stackoverflow
Solution 17 - AndroidVladView Answer on Stackoverflow
Solution 18 - AndroidPirateView Answer on Stackoverflow
Solution 19 - Androidgiorgos.nlView Answer on Stackoverflow
Solution 20 - AndroidIshrakView Answer on Stackoverflow