防止在 EditText 上输入键,但仍将文本显示为多行

如何在 Android 上创建一个 EditText,这样用户可能不会输入多行文本,但显示仍然是多行的(即有文字换行而不是文本到右边) ?

它类似于内置的 SMS 应用程序,我们不能输入换行符,但文本显示在多行中。

67265 次浏览

我将子类化小部件并覆盖密钥事件处理,以阻塞 Enter密钥:

class MyTextView extends EditText
{
...
@Override
public boolean onKeyDown(int keyCode, KeyEvent event)
{
if (keyCode==KeyEvent.KEYCODE_ENTER)
{
// Just ignore the [Enter] key
return true;
}
// Handle all other keys in the default way
return super.onKeyDown(keyCode, event);
}
}

试试这个:

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_ENTER)
{
//Nothing
return true;
}
return super.onKeyDown(keyCode, event);
}

这是一个不必重写 EditText 类的方法。您只需捕获并用空字符串替换换行。

edittext.addTextChangedListener(new TextWatcher() {


public void onTextChanged(CharSequence s, int start, int before, int count) {


}


public void beforeTextChanged(CharSequence s, int start, int count, int after) {


}


public void afterTextChanged(Editable s) {
/*
* The loop is in reverse for a purpose,
* each replace or delete call on the Editable will cause
* the afterTextChanged method to be called again.
* Hence the return statement after the first removal.
* http://developer.android.com/reference/android/text/TextWatcher.html#afterTextChanged(android.text.Editable)
*/
for(int i = s.length()-1; i >= 0; i--){
if(s.charAt(i) == '\n'){
s.delete(i, i + 1);
return;
}
}
}
});

这要归功于 劳夫对早期答案的改进。

我正在测试这个,它似乎起作用了:

EditText editText = new EditText(context);
editText.setSingleLine(false);
editText.setInputType(android.text.InputType.TYPE_CLASS_TEXT | android.text.InputType.TYPE_TEXT_VARIATION_EMAIL_SUBJECT);

将这个属性添加到 EditText XML 对我来说很有用:

android:lines="1"

它允许用户输入换行符,但是 EditText本身不会增加高度。


属性

android:lines="5"
android:inputType="textPersonName"

对于 URI,你可以使用:

android:inputType="textUri"
android:lines="1"
android:maxLength="128"

否则,上面提到的 android:inputType="textPersonName"适用于其他 EditText,如用户名等。

<EditText
android:id="@+id/Msg"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dip"
android:lines="5"
android:selectAllOnFocus="true"
android:hint="Skriv meddelande...\n(max 100tkn)"/>




EditText et = (EditText)findViewById(R.id.Msg);
String strTmp = et.getText().toString();
strTmp = strTmp.replaceAll("\\n"," ");

这个适合我:

<EditText
android:inputType="textShortMessage|textMultiLine"
android:minLines="3"
... />

它显示一个笑脸,而不是回车键。

接受的答案工作得非常好,直到我将带有分行符的文本复制到 EditText 中。因此,我添加了 onTextContextMenuItem 来监视粘贴操作。

@Override
public boolean onTextContextMenuItem(int id) {
boolean ret = super.onTextContextMenuItem(id);
switch (id) {
case android.R.id.paste:
onTextPaste();
break;
}
return ret;
}


public void onTextPaste() {
if (getText() == null)
return;
String text = getText().toString();
text = text.replaceAll(System.getProperty("line.separator"), " ");
text = text.replaceAll("\\s+", " ");
setText(text);
}
    EditText textView = new EditText(activity);
...
textView.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView textView, int i, KeyEvent keyEvent) {
if(KeyEvent.KEYCODE_ENTER == keyEvent.getKeyCode()) {
return false;
}
.......


}
});

您可以像下面这样从 xml 设置它:

android:imeOptions="actionDone"
android:inputType="text"
android:maxLines="10"

不要忘了 android:inputType="text",如果你不设置它,它不工作。我不知道为什么。 也不要忘记将 maxLines改为您的首选值。

只要加上

        android:singleLine="true"

发送到您的 EditText

由@Andreas Rudolph 提供的答案包含一个关键的错误,不应该被使用。当您经过包含多个新行字符的 EditText中的文本时,该代码将导致 IndexOutOfBoundsException。这是由所使用的循环类型引起的,Editable对象将在其内容发生变化(替换、删除、插入)时立即调用 afterTextChanged方法。

密码正确:

edittext.addTextChangedListener(new TextWatcher() {


public void onTextChanged(CharSequence s, int start, int before, int count) {


}


public void beforeTextChanged(CharSequence s, int start, int count, int after) {


}


public void afterTextChanged(Editable s) {
/*
* The loop is in reverse for a purpose,
* each replace or delete call on the Editable will cause
* the afterTextChanged method to be called again.
* Hence the return statement after the first removal.
* http://developer.android.com/reference/android/text/TextWatcher.html#afterTextChanged(android.text.Editable)
*/
for(int i = s.length()-1; i >= 0; i--){
if(s.charAt(i) == '\n'){
s.delete(i, i + 1);
return;
}
}
}
});

我将提供另一个选项,这样您就不必继承 EditText。创建一个过滤掉换行符的 InputFilter。然后使用 EditText.addInputFilter

这种输入过滤器的源代码如下: https://gist.github.com/CapnSpellcheck/7c72830e43927380daf5205100c93977

可以在构造函数中传递0,它不允许任何换行。此外,您还可以将其与其他调整(如 android:imeOptions="actionDone")结合起来,因为这将有助于改善某些设备上的体验。

这里有一个更正确的答案,它没有在 IME 键盘上显示回车键:

// IMPORTANT, do this before any of the code following it
myEditText.setSingleLine(true);


// IMPORTANT, to allow wrapping
myEditText.setHorizontallyScrolling(false);
// IMPORTANT, or else your edit text would wrap but not expand to multiple lines
myEditText.setMaxLines(6);

另外,您可以用 XML 布局文件中的显式 android:inputType或代码中的 setInputType(InputType.*)来替换 setSingleLine(true)——其中,使用的输入类型是您知道的任何东西,只能将输入限制为单行(即,已经隐式调用 setSingleLine(true)的任何东西)。


说明:

setSingleLine(true)所做的是隐式地调用 setHorizontallyScrolling(true)setLines(1),同时修改一些 IME 键盘设置以禁用输入键。

反过来,对 setLines(1)的调用就像在一次调用中调用 setMinLines(1)setMaxLines(1)一样。

一些输入类型(例如,来自 InputType.TYPE_*的常量)隐式地调用 setSingleLine(true),或者至少达到同样的效果。

结论:

因此,为了实现 OP 想要的结果,我们只需要通过恢复那些隐式调用来抵消那些隐式设置。

这就是解决办法。

<EditText
android:id="@+id/editText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLength="150"
android:textSize="15dp"
android:imeOptions="actionDone"
android:inputType="text|textMultiLine"/>

Java 类中的用法

editText.setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View view, int keyCode, KeyEvent event) {


if (keyCode==KeyEvent.KEYCODE_ENTER)
{
// Just ignore the [Enter] key
return true;
}
// Handle all other keys in the default way
return (keyCode == KeyEvent.KEYCODE_ENTER);
}
});

您可以从代码中更改操作按钮

editText.imeOptions = EditorInfo.IME_ACTION_DONE
editText.setRawInputType(InputType.TYPE_CLASS_TEXT)

Xml

android:inputType="textMultiLine"