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


71

如何在Android上制作EditText,以使用户可能无法输入多行文本,但显示仍然是多行(即,有自动换行而不是在右侧显示文本)?

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


11
只需将android:inputType =“ textPersonName”添加到EditText,它将阻止按Enter键
AndroidGeek

Answers:


49

我将子类化为小部件并重写键事件处理,以阻止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);
    }
}

4
这行代码return super.onKeyDown(keyCode, event);应该在onKeyDown还是我在想象中?:P
necixy

我们俩都在同一个社区工作。不用客气。:)
necixy

11
感谢您的回答。(我也增加了其他答案)。提示:您可以仅通过editText.setOnKeyListener(...)避免子类化,并返回(keyCode == KeyEvent.KEYCODE_ENTER)。
Randy Sugianto'Yuku'2011年

2
Enter键仍在具有线性布局的关系中工作
aNdRO博士2014年

3
几乎没有键盘实际发送按键事件。这些是用于硬件密钥的。他们几乎都使用commitText,而不会调用此函数。
·塞尚

48

这是一种方法,您不必重写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;
        }
    }
}
});

感谢罗尔夫对较早的答案改善。


3
+1对于我来说,这比公认的答案更有用,原因很简单,我可以将其用作TextWatcher的默认实现,可以通过子类对其进行扩展(然后将其简单地调用super.afterTextChanged(... )保留该换行检查支票!
AgentKnopf 2012年

1
循环条件应为i > 0而不是i >= 0。什么时候i == 0s.subSequence(i-1, i)得到一个IndexOutOfBoundsException
TalkLittle 2014年

2
我认为这会为带有新行的文本抛出IndexOutOfBoundsException,该行将被复制并粘贴有多个新行字符。
Chriskot 2015年

1
@TalkLittle我用正确的代码发布了另一个答案,只是更改for循环条件并不能解决IndexOufOfBoundsException。见我的回答:stackoverflow.com/a/36485266/1052697
Rolfツ

23

XML属性

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

谢谢,最简单的!尽管我注意到它阻止了ET上的点击侦听器正常工作,但editText.setSingleLine(false);如果可以,请改用它。
Azurespot

这完全取决于所使用的键盘。许多人仍会显示回车键
Gabe Sechan

14

这对我有用:

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

它显示一个笑脸而不是Enter键。


2
根据经验,这并不是在每个键盘上都适用。我们附近的HTC手机仍然显示Enter键。
树线

这完全取决于所使用的键盘。许多人仍会显示回车键
Gabe Sechan

如果您长按Nexus 6中的笑脸按钮,则仍然可以添加换行符。因此,这不是通用的解决方案。
小学

8

@Andreas Rudolph提供的答案包含一个严重的错误,不应使用。IndexOutOfBoundsException当您在EditText其中包含多个换行符的文本过去时,该代码会导致。这是由所使用的循环类型引起的,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;
            }
        }
    }
});

您应该已经编辑了答案,而不是重新编写答案。
罗伯特·马丁

@RobertMartin我本人对此很纳闷,并在Meta网站上寻求帮助,他们建议我应该发布一个新答案。因为我所做的更改与作者的原始意图相抵触。
罗尔夫(Rolf)2013年

1
真好!但是,如果您按Enter键开始,则开头仍会有新行(因此i>=0应该可以使用)^^
fllo

不错的解决方案。对于某人在Kotlin中寻找代码的人:for(i in s.length-1 downTo 0){if(s [i] =='\ n'){s.delete(i,i + 1)return}}
Annsh辛格

1
做完@Rolfツ!感谢您的改进
Andreas Rudolph

8

这是一个更正确的答案,该答案未在IME键盘上显示Enter键:

// 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布局文件上的setSingleLine(true)显式android:inputTypesetInputType(InputType.*)代码上的显式代替-在其中使用的输入类型是您所知道的将输入限制为仅一行的任何内容(即,setSingleLine(true)已经隐式调用的任何内容)。


说明:

什么setSingleLine(true)做呼吁setHorizontallyScrolling(true)setLines(1)含蓄,与一起改变一些输入法键盘设置禁用回车键。

反过来,调用setLines(1)像调用setMinLines(1)setMaxLines(1)一个电话。

某些输入类型(即from中的常量InputType.TYPE_*)会setSingleLine(true)隐式调用,或至少会达到相同的效果。

结论:

因此,要实现OP所需的功能,我们只需通过还原那些隐式调用来对那些隐式设置进行计数。


5

我正在对此进行测试,它似乎可以工作:

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

太好了,谢谢。在XML中设置任何内容都会禁用我的ET Click侦听器...因此,这样做并没有!键盘上的返回键变为“完成”按钮。(我只需要editText.setSingleLine(false);)。
Azurespot '16

这完全取决于所使用的键盘。许多人仍会显示Enter键
Gabe Sechan

5

尝试这个:

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

2
否。这会将编辑限制为一行。OP需要多行;他只是不希望用户能够输入换行符。

几乎没有键盘实际发送按键事件。这些是用于硬件密钥的。他们几乎都使用commitText,而不会调用此函数。
Gabe Sechan

3

您可以从xml进行设置,如下所示:

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

别忘了android:inputType="text",如果您不设置它,它将不起作用。我不知道为什么。另外,不要忘记更改maxLines为您的首选值。


这完全取决于所使用的键盘。许多人仍会显示Enter键
Gabe Sechan


2

这是解决方案...

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

欢迎来到SO。感谢您的回答。您能否正确设置其格式,例如将文本和代码部分分隔为 Here is the solution...?其他一些背景信息也有帮助。谢谢。
CKE

1

在我将带有换行符的文本复制到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);
}

1

您可以通过代码更改操作按钮

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

Xml

android:inputType="textMultiLine"

0
<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"," ");

0
    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;
            }
            ....... 

        }
    });

0

对于URI,您可以使用:

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

否则android:inputType="textPersonName",如上所述,它适用于其他EditText,例如用户名等。


0

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

这样的输入过滤器的源代码在这里:https : //gist.github.com/CapnSpellcheck/7c72830e43927380daf5205100c93977

您可以在构造函数中传递0,并且不允许任何换行符。另外,您可以将其与其他调整之一结合使用,例如android:imeOptions="actionDone",因为这将有助于改善某些设备上的体验。


-1

将此属性添加到EditTextXML对我有用:

android:lines="1"

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

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.