EditText maxLines не працює - користувач все одно може вводити більше рядків, ніж встановлено


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

Користувач може ввести більше 5 рядків, натиснувши клавішу Enter / Наступний рядок. Як я можу обмежити введення користувачем фіксованої кількості рядків за допомогою EditText?


Побачити цей пост: stackoverflow.com/questions/14672234 / ...
али safaei

Відповіді:


85

Атрибут maxLinesвідповідає максимальній висоті EditText, він контролює зовнішні межі, а не внутрішні рядки тексту.


Ось, що я думав також ... Чи є спосіб обмежити введені рядки або мені це потрібно програмним кодом програмно?
Індрек Кюе

Не існує простого способу обмеження введених ліній так, як вам потрібно. Це вам доведеться зробити в коді вручну.
Cedekasme

3
Я думаю, що для розробника "maxLines" має на увазі максимальну кількість рядків, яка повинна бути можливою за допомогою editText. Якби я просто хотів певної висоти, я б використав "лінії". : - /
Хтось десь

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

Вам просто потрібно переконатися, що у вас встановлений атрибут "inputType". Без цієї лінії це не працює.

android:inputType="text"

3
@Neol Chew Ви праві! Я працював після встановлення inputTypeна text. Дякую, що
заощадили

6
@byJeevan, я завжди вважав, що inputType має значення за замовчуванням "текст". Здогадайтесь, я помилявся.
Ноель Чеу

2
Дуже дивно, що для тексту input не встановлено значення за замовчуванням. Хоча велика відповідь
Мухаммед Refaat

9
він працює лише для maxLines 1, але ви не можете додати новий рядок
Даніель Рауф

69

Це не вирішує загального питання обмеження на n рядків. Якщо ви хочете обмежити EditText лише 1 рядком тексту, це може бути дуже просто.
Ви можете встановити це у файлі xml.

android:singleLine="true"

або програмно

editText.setSingleLine(true);

8
але що робити, якщо ви хочете обмежитися 2 рядами? або 3? Для цього вам потрібно створити спеціальний обмежувач рядків ...
Індрек Кюе

4
Я це знаю. "Це не вирішує загального питання обмеження на n рядків". Я закінчив прочитати тут питання, коли я намагався обмежитися 1 рядком і знайшов простіше рішення. Я подумав, що інші можуть виявитись тут, намагаючись обмежити свій редактор редагування до 1 рядка та застосувати "спеціальний обмежувач рядків". Моя відповідь є для інших користувачів SO, які закінчують пошук цього питання з тієї ж причини, що і я.
Джессі Блек

@ IndrekKõue, що не повинно бути занадто важким.
Дон Ларинкс

10
застарілий singleLine
Алі

1
атрибут editText singleLine = "true" є застарілим, і він вийде з ладу на пристроях, які використовуються на Android більше 7,0
TranHieu

24

@Cedekasem ви праві, немає вбудованого "обмежувача рядків". Але я створив своє власне «я», тому, якщо когось цікавить, код нижче. Ура.

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

Це має неінтуїтивний побічний ефект для користувача. наприклад, якщо у вашому редагуванні текстових файлів 7 рядків, а потім натисніть клавішу в середині, тоді ви можете прощатися до останнього рядка тексту.
miguel.martin

не буде працювати, якщо ви вставите більше, ніж максимальний текст. Тому краще було б використовувати addTextChangedListener.
Kuldeep Sakhiya

13

Я зробив щось, як ви, хлопці, шукали. Ось мояLimitedEditText клас.

Особливості:

  • ви можете обмежити кількість ліній у своєму компоненті LimitedEditText
  • ви можете обмежити кількість символів у вашому компоненті LimitedEditText
  • якщо ви перевищите ліміт символів або рядків десь посередині тексту, курсор
    не доведе до кінця - він залишиться там, де ви були.

Я вимикаю слухача, тому що кожен дзвінок setText() методу буде рекурсивно викликати ці 3 способи зворотного виклику у випадку, коли користувач перевищив ліміт символів чи рядків.

Код:

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

}

2
Це рішення таке просте і елегантне! Спасибі
GuilhE

Я використовую beforeCursorPosition = getSelectionStart();при afterTextChangedзворотній дзвінок. Він працює краще , тому що , коли набравши eпісля введення abcd, то EditText може «думати» замінити abcdз abcde, з - за методу введення причини.
hanswim

11

Я зробив для цього простіше рішення: 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);
        }
    });

Ви можете змінити значення 3 в txtSpecialRequests.getLineCount() > 3для ваших потреб.


3
Дякую вам, нарешті спрацювали після декількох неправильних рішень. Це має бути прийнятою відповіддю.
eyadMhanna

Я розумію, що "txtSpecialRequests" - це ваш контейнер EditText, але де ви встановлюєте змінні lastSpecialRequestsCursorPosition та specialRequests?
drearypanoramic

за межами цього методу :) init lastSpecialRequestsCursorPosition = 0 та specialRequests = ""
Оскар Юандіната

Чудове рішення!
Маркус

5

Ось InputFilter, який обмежує дозволені рядки в 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;
  }
}

Щоб додати його до EditText:

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

Хороше рішення, однак воно вирішує проблему обгортання тексту (не вводити)
Пітер Файл

4

Це те, що я використовував у своєму проекті:

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

І це спрацювало у всіх сценаріях


1
Який контекст потрібен TextWatcher? KeyListener був усім, що мені було потрібно.
AlanKley

@AlanKley: Для обчислення кількості рядків editText нам потрібно до і після зміни подій, що змінюються текстом. Ніби ми продовжуємо вводити текст і не натискаємо клавішу "новий рядок", тоді onKey не спрацьовує, і курсор автоматично переходить до наступного рядка. Тож для відстеження таких рядків нам потрібен textWatcher. Я сподіваюся, що я зможу зробити вас зрозуміти.
Пірат

Я бачу. Дякую за пояснення.
AlanKley

@AlanKley Якщо ви вважаєте, що моя відповідь корисна, будь ласка, проголосуйте за неї.
Пірат

public void afterTextChanged (Editable arg0) {int lineCount = editText.getLineCount (); if (lineCount> numberOfLines) {editText.setText (текст); }} викине StackOverflowException ...
desgraci


3

Найпростіше рішення:

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



1

Ще один спосіб обмежити ваш EditTextрядок:

editText2.setTransformationMethod(new SingleLineTransformationMethod());

Зауважте, що після застосування цього методу перетворення клавіша введення створює пробіли при натисканні. Це все ще задовольняє питання ТС.


Гарний спосіб приховування нової лінії! У значенні, однак, все ще буде символ "нового рядка" !!
Григорій Штейн

1

Ви можете обмежити текст відповідно до кількості рядків. Я кажу, що біля 37 алфавітів в одному рядку

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

0

getLineCount () - один варіант; якщо ви хочете ненульові значення, переконайтеся, що ваш погляд вимірюється. Для м'якої клавіатури onKeyListener не працюватиме, тому вам доведеться додати addTextChangedListener (), який буде відслідковувати зміни тексту під час введення. Як тільки ви отримаєте достатню кількість ліній всередині його зворотних дзвінків, виконайте все, що ви хочете обмежити: видаліть символи за допомогою getText (), setText () або щось більш фантазійне. Можна навіть обмежити кількість символів за допомогою фільтра.

Інший варіант - відстежувати розмір тексту за допомогою getLineBounds (). Це буде взаємодіяти з гравітацією тексту / paddign, тому будьте обережні.


0

Для обмеження кількості символів ми можемо просто використовувати властивість maxLength EditText, оскільки це не дозволить користувачеві вводити більше символів.


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

0

Інша ідея: кожен раз після введення нового тексту буде зберігатися в String lastText, лише якщо кількість рядків не перевищує MAX_LINES. Якщо це так, ми встановимо текст EditText до останнього доданого тексту (таким чином зміни будуть видалені) та сповістимо користувача, щоб він був коротким.

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

0

Це продовження відповіді Індрека Кюе до Котліна

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

-4

Спробуйте використати таку комбінацію атрибутів EditText у файлі xml:

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


2
Просто голови вгору. SingleLine застарілий. maxLines був введений замість singleLine.
Sandeep R

@SandeepR Ви неправі, android:inputTypeзамінює використанняandroid:singleLine
П'єр,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.