Ответ 1
Атрибут maxLines
соответствует максимальной высоте EditText
, он управляет внешними границами, а не внутренними текстовыми строками.
<EditText
android:id="@+id/editText2"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:maxLines="5"
android:lines="5">
</EditText>
Пользователь может ввести более 5 строк, нажав клавишу ввода/следующей строки. Как я могу ограничить ввод пользователя фиксированным количеством строк с помощью EditText?
Атрибут maxLines
соответствует максимальной высоте EditText
, он управляет внешними границами, а не внутренними текстовыми строками.
<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"
Это не решает общей проблемы ограничения n строк. Если вы хотите ограничить редактирование текста EditText только одной строкой текста, это может быть очень просто.
Вы можете установить это в файле xml.
android:singleLine="true"
или программно
editText.setSingleLine(true);
@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;
}
});
Я сделал то, что вы, ребята, искали. Здесь мой класс LimitedEditText
.
Особенности:
Im отключает прослушиватель, потому что каждый вызов метода setText()
рекурсивно вызывает эти три метода обратного вызова в случае, если пользователь превысил лимит символов или строк.
код:
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);
}
}
Я сделал более простое решение для этого: 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
в соответствии с вашими потребностями.
Вот 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)});
Это то, что я использовал в своем проекте:
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;
}
});
И он работал во всех сценариях
getLineCount() - один из вариантов; если вы хотите отличные от нуля значения, убедитесь, что ваш вид измерен. Для мягкой клавиатуры onKeyListener не будет работать, поэтому вам нужно добавить addTextChangedListener(), который будет отслеживать изменения текста по мере ввода. Как только вы получите достаточное количество строк внутри своих обратных вызовов, сделайте все, что вы хотите ограничить: удалите символы с getText(), setText() или что-то более фантастическое. Вы можете даже ограничить количество символов с помощью фильтра.
Другой вариант - контролировать размер текста с помощью getLineBounds(). Это будет взаимодействовать с гравитацией текста /paddign, поэтому будьте осторожны.
Для предельного числа символов мы можем просто использовать свойство maxLength для EditText, так как оно не позволит пользователю вводить больше символов.
Самое простое решение:
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());
}
Другой способ ограничить EditText
одной строкой:
editText2.setTransformationMethod(new SingleLineTransformationMethod());
Обратите внимание, что после применения этого метода преобразования клавиша ввода создает пробелы при нажатии. Это все еще удовлетворяет вопросу TS.
Попробуйте использовать следующую комбинацию атрибутов EditText внутри xml файла:
android:singleLine="true"
android:maxLength="22"