【问题标题】:Prevent enter key on EditText but still show the text as multi-line防止在 EditText 上输入键,但仍将文本显示为多行
【发布时间】:2011-08-29 13:45:13
【问题描述】:

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

类似于内置短信应用,我们不能输入换行符,但文本显示为多行。

【问题讨论】:

  • 只需将 android:inputType="textPersonName" 添加到 EditText 它将阻止它按 enter

标签: android android-edittext multiline


【解决方案1】:

我会将小部件子类化并覆盖键事件处理以阻止 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);
    }
}

【讨论】:

  • 这行:return super.onKeyDown(keyCode, event); 应该在 onKeyDown 中还是我在想象? :P
  • 我们都在为同一个社区工作。不客气,珍。 :)
  • 感谢您的回答。 (我也提高了另一个答案)。提示:您可以通过仅 editText.setOnKeyListener(...) 并返回 (keyCode == KeyEvent.KEYCODE_ENTER) 来避免子类化。
  • 回车键仍在线性布局的关系中工作
  • 几乎没有键盘实际发送按键事件。这些是用于硬件键的。他们几乎都使用了commitText,它不会调用这个函数。
【解决方案2】:

试试这个:

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

【讨论】:

  • 没有。这将编辑限制为一行。 OP想要多行;他只是不希望用户能够输入换行符。
  • 几乎没有键盘实际发送按键事件。这些是用于硬件键的。他们几乎都使用了commitText,它不会调用这个函数。
【解决方案3】:

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

感谢Rolf 以改进较早的答案。

【讨论】:

  • +1 在我的情况下,这比接受的答案更有用,原因很简单,我可以将它用作 TextWatcher 的默认实现,它可以通过子类进行扩展(然后简单调用 super.afterTextChanged(...) 以保留对换行符的检查。有效!
  • For-loop 条件应该是i > 0 而不是i >= 0。当i == 0s.subSequence(i-1, i) 得到一个IndexOutOfBoundsException
  • 我认为这会引发 IndexOutOfBoundsException 文本的新行复制并粘贴多个换行符。
  • @TalkLittle 我用正确的代码发布了另一个答案,仅更改 for 循环条件并不能修复 IndexOufOfBoundsException。看我的回答:stackoverflow.com/a/36485266/1052697
【解决方案4】:

我正在测试它,它似乎工作:

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 点击监听器......所以这样做没有!键盘上的返回键变为“完成”按钮。 (我只需要editText.setSingleLine(false);)。
  • 这完全取决于使用的键盘。许多人仍会显示回车键
【解决方案5】:

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

android:lines="1"

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

【讨论】:

    【解决方案6】:

    XML 中的属性

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

    【讨论】:

    • 谢谢,最简单的!虽然我注意到它阻止了我在 ET 上的点击监听器工作......所以如果是这样,请改用editText.setSingleLine(false);
    • 这完全取决于使用的键盘。许多人仍会显示回车键
    【解决方案7】:

    对于URI,您可以使用:

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

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

    【讨论】:

      【解决方案8】:
      <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"," ");
      

      【讨论】:

        【解决方案9】:

        这个对我有用:

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

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

        【讨论】:

        • 根据经验,这并不适用于每个键盘。我们身边的一部 HTC 手机仍然显示回车键。
        • 这完全取决于使用的键盘。许多人仍会显示回车键
        • 如果您在 Nexus 6 中长按笑脸按钮,那么您仍然可以添加换行符。因此,这不是一般的解决方案。
        【解决方案10】:

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

        【讨论】:

          【解决方案11】:
              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;
                      }
                      ....... 
          
                  }
              });
          

          【讨论】:

            【解决方案12】:

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

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

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

            【讨论】:

            • 这完全取决于使用的键盘。许多人仍会显示回车键
            【解决方案13】:

            简单添加

                    android:singleLine="true"
            

            到你的 EditText

            【讨论】:

            • 已弃用!
            【解决方案14】:

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

            【讨论】:

            • 您应该编辑答案,而不是制作新答案。
            • @RobertMartin 我自己也想知道这个问题并在 Meta 网站上寻求帮助,他们建议我应该发布一个新答案。因为我所做的更改与作者的原意相冲突。
            • 不错!但是,如果您从按 Enter 键开始,您仍然会在开头有一个新行(所以 i&gt;=0 应该可以工作)^^
            • 不错的解决方案。对于在 Kotlin 中寻找代码的人: for (i in s.length - 1 downTo 0) { if(s[i] == '\n') { s.delete(i, i + 1) return } }跨度>
            • 完成@Rolfツ!感谢改进
            【解决方案15】:

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

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

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

            【讨论】:

              【解决方案16】:

              这是一个更正确的答案,在 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);
              

              此外,您可以将setSingleLine(true) 替换为 XML 布局文件上的显式 android:inputType 或代码上的 setInputType(InputType.*) - 其中,使用的输入类型是您知道的将输入限制为单个的任何内容仅行(即,任何已经隐式调用 setSingleLine(true) 的内容)。


              说明:

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

              反过来,对setLines(1) 的调用就像同时调用setMinLines(1)setMaxLines(1)

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

              结论:

              因此,为了实现 OP 想要的,我们只需通过还原那些隐式调用来对抗那些隐式设置。

              【讨论】:

                【解决方案17】:

                这是解决方案....

                <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...?一些更多的背景信息也很有帮助。谢谢。
                • keyCode==KeyEvent.KEYCODE_ENTER 时,您已经返回true。所以,next 将返回false
                【解决方案18】:

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

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

                XML

                android:inputType="textMultiLine"
                

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 2014-01-21
                  • 2022-01-18
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多