EditText maxLines不起作用-用户仍然可以输入多于设置的行


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

用户可以按回车/下一行键输入5行以上。如何使用EditText将用户输入限制为固定的行数?


Answers:


84

该属性maxLines对应于的最大高度EditText,它控制外部边界,而不控制内部文本行。


那也是我的想法...有没有办法限制输入的行,或者我必须以编程方式在后端代码上使用它?
IndrekKõue2011年

没有简单的方法可以随意限制输入的行数。您必须在代码中手动进行操作。
Cedekasme,2011年

3
我认为对于开发人员来说,“ maxLines”暗示了editText应该可以的最大行数。如果我只想指定特定的高度,可以使用“线”。:-/
某处某人2014年

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。感谢您节省我的时间:-)
Jeevan '17

6
@byJeevan,我一直认为inputType的默认值为“ text”。猜猜我错了。
诺埃尔咀嚼

2
很奇怪,Text不是为inputType设置默认值,虽然很好回答
Muhammed Refaat

9
它仅适用于1的maxLines,但您不能添加新行
Daniel Raouf

68

这不能解决限制为n行的一般问题。如果您想将EditText限制为仅接受1行文本,这可能非常容易。
您可以在xml文件中进行设置。

android:singleLine="true"

或以编程方式

editText.setSingleLine(true);

8
但是如果您想限制为2行呢?还是3?为此,您必须构建自定义行限制器...
IndrekKõue2011年

4
我知道。“这不能解决限制为n行的一般问题”。当我试图限制为1行时,我最终在这里阅读了该问题,并找到了一个更简单的解决方案。我认为其他人可能最终希望将其EditText限制为1行并实现“自定义行限制器”。我的答案在这里,是出于与我相同的原因而最终搜索此问题的其他SO用户。
杰西·布莱克

@IndrekKõue应该不太难。
Don Larynx

10
singleLine已弃用
阿里(Ali)

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

这对于用户而言具有非直觉的副作用。例如,如果您在EditText中有7行,然后在其中间按Enter,则可以说再见到文本的最后一行。
miguel.martin

如果您在其中粘贴的行数超过maxlines,则无法使用。因此,最好使用addTextChangedListener。
Kuldeep Sakhiya '16

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 2014年

我用beforeCursorPosition = getSelectionStart();afterTextChanged回调中。效果更好,因为键入e后键入时abcd,EditText可能会“认为”您替换abcdabcde,因为输入法的原因。
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);
        }
    });

您可以根据txtSpecialRequests.getLineCount() > 3需要更改3 in的值。


3
非常感谢,在解决了多个错误的解决方案后终于工作了。这应该是公认的答案。
eyadMhanna 2015年

我知道“ txtSpecialRequests”是您的EditText容器,但是您在哪里设置变量lastSpecialRequestsCursorPosition和specialRequests?
drearypanoramic 2015年

当然不在此方法之外:) init lastSpecialRequestsCursorPosition = 0和specialRequests =“”
Oscar Yuandinata

很好的解决方案!
马库斯'18

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

好的解决方案,但是它确实解决了文本换行(不输入)的问题
Peter File

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。
AlanKley13年

@AlanKley:我们需要在文本更改事件之前和之后计算出editText的行数。就像我们继续输入文本并且没有按“换行”键一样,onKey也不会触发,并且光标会自动移至下一行。因此,要跟踪这些行,我们需要textWatcher。希望我能使您理解。
海盗

我懂了。感谢您的澄清。
AlanKley13年

@AlanKley如果您认为我的回答有用,请投票。
海盗

public void afterTextChanged(Editable arg0){int lineCount = editText.getLineCount(); if(lineCount> numberOfLines){editText.setText(text); }}将引发StackOverflowException ...
desgraci 2014年


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

请注意,应用此转换方法后,按Enter键会创建空格。这仍然可以满足TS的问题。


隐藏新行的好方法!但是,在值中,仍然会有“换行”字符!
格雷戈里·斯坦

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

对于字符数的限制,我们可以简单地使用EditText的maxLength属性,因为它将不允许用户输入更多字符。


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

另一个想法:每次输入后,仅当行数不超过MAX_LINES时,新文本才会保存到String lastText中。如果是这样,我们将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

这是IndrekKõue对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)
                    }
                }
            })

-4

尝试在xml文件中使用EditText的以下属性组合:

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


2
只是抬头。不建议使用singleLine。引入了maxLines来代替singleLine。
Sandeep R

@SandeepR您错了,android:inputType取而代之的是android:singleLine
Pierre
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.