Indrek Kõue
Indrek Kõue

Reputation: 6449

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

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

Upvotes: 159

Views: 111437

Answers (20)

Eldot
Eldot

Reputation: 1

For a single line input, you can use the inputType="text" attribute, but for multiline input, you need to add:

android:maxLines="2"
android:inputType="textMultiLine"

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

Upvotes: 2

Amir Golan
Amir Golan

Reputation: 524

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

Upvotes: 2

Adri&#225;n Prieto
Adri&#225;n Prieto

Reputation: 377

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

Upvotes: 14

Vimal Prabhu
Vimal Prabhu

Reputation: 99

set editText android:inputType="text"

Upvotes: 10

Nafees
Nafees

Reputation: 1034

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

Upvotes: 5

Atiar Talukdar
Atiar Talukdar

Reputation: 746

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

Upvotes: 2

mohammed nathar
mohammed nathar

Reputation: 190

this is one approach. Might help someone.

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

Upvotes: 3

giorgos.nl
giorgos.nl

Reputation: 2832

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.

Upvotes: 0

Noel Chew
Noel Chew

Reputation: 3933

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

Upvotes: 297

bitanon
bitanon

Reputation: 135

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

Upvotes: 5

Indrek K&#245;ue
Indrek K&#245;ue

Reputation: 6449

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

Upvotes: 26

Oscar Yuandinata
Oscar Yuandinata

Reputation: 1035

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.

Upvotes: 14

peceps
peceps

Reputation: 17557

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

Upvotes: 6

Pirate
Pirate

Reputation: 545

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

Upvotes: 5

bpawlowski
bpawlowski

Reputation: 1046

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

}

Upvotes: 16

Pirate
Pirate

Reputation: 545

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

Upvotes: 0

Vlad
Vlad

Reputation: 4525

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.

Upvotes: 0

Jesse Black
Jesse Black

Reputation: 7976

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

Upvotes: 76

Cedekasme
Cedekasme

Reputation: 2037

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

Upvotes: 97

Related Questions