【问题标题】:Multi-line EditText with Done action button带有完成操作按钮的多行 EditText
【发布时间】:2011-02-28 12:09:42
【问题描述】:

是否可以同时设置android:inputType="textMultiLine"android:imeOptions="actionDone"EditText 小部件?

我想要一个多行编辑框,键盘上的操作按钮是 Done,而不是 Enter(回车),但它似乎不起作用。

【问题讨论】:

标签: android


【解决方案1】:

如果您使用 DataBinding,您应该创建一个可以捕获操作的方法。另见https://stackoverflow.com/a/52902266/2914140

一些带有扩展方法的文件,例如BindingAdapters.kt:

@BindingAdapter("inputType", "action")
fun EditText.setMultiLineCapSentencesAndDoneAction(inputType: Int, callback: OnActionListener?) {
    setRawInputType(inputType)
    if (callback == null) setOnEditorActionListener(null)
    else setOnEditorActionListener { v, actionId, event ->
        if (actionId == EditorInfo.IME_ACTION_DONE ||
            event?.keyCode == KeyEvent.KEYCODE_ENTER && event.action == KeyEvent.ACTION_DOWN
        ) {
            callback.enterPressed()
            return@setOnEditorActionListener true
        }
        return@setOnEditorActionListener false
    }
}

interface OnActionListener {
    fun enterPressed()
}

然后在 XML 中:

<data>
    <variable
        name="viewModel"
        type="YourViewModel" />

    <import type="android.text.InputType" />
</data>

<EditText
    android:imeOptions="actionDone"
    android:inputType=""
    app:action="@{() -> viewModel.send()}"
    app:inputType="@{InputType.TYPE_TEXT_FLAG_CAP_SENTENCES | InputType.TYPE_TEXT_FLAG_MULTI_LINE}" />

【讨论】:

    【解决方案2】:

    可重用的 Kotlin 解决方案

    在代码中设置这些值是唯一对我有用的方法

    edittext.inputType = EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE
    edittext.setHorizontallyScrolling(false)
    edittext.maxLines = Integer.MAX_VALUE // Or your preferred fixed value
    

    我经常需要这个,所以这样做是为了保持代码干净:

    fun EditText.multilineIme(action: Int) {
        imeOptions = action
        inputType = EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE
        setHorizontallyScrolling(false)
        maxLines = Integer.MAX_VALUE
    }
    
    // Then just call
    edittext.multilineIme(EditorInfo.IME_ACTION_DONE)
    

    如果您想在“完成”上添加可选的自定义操作,请尝试以下操作:

    fun EditText.multilineDone(callback: (() -> Unit)? = null) {
        val action = EditorInfo.IME_ACTION_DONE
        multilineIme(action)
        setOnEditorActionListener { _, actionId, _ ->
                if (action == actionId) {
                    callback?.invoke()
                    true
                }
                false
            }
        }
    }
    
    // Then you can call
    edittext.multilineDone { closeKeyboard() }
    
    // or just
    edittext.multilineDone()
    

    需要在回调中轻松控制键盘? Read this post

    然后添加hideKeyboard()调用EditText.multilineDone

    【讨论】:

    • ☝️这是一个很好的答案
    【解决方案3】:

    我认为这是做你的事情的方式。拥有android:inputType="textMultiLine"android:imeOptions="actionDone" 会使输入键功能不明确。请记住,您可以使用android:lines="10",也可以删除android:inputType="textMultiLine",但这取决于您想要实现的目标,有时您只需要android:inputType="textMultiLine",并且没有替代品。

    EditText ed=new EditText(this);
    ed.setOnKeyListener(new OnKeyListener() {
            @Override
            public boolean onKey(View v, int keyCode, KeyEvent event) {
                if(keyCode == KeyEvent.KEYCODE_ENTER){
                    //do your stuff here
                }
                return false;
            }
    });
    

    【讨论】:

    • 使用固定数量的最大数字和 android:lines="10" 对我有用,在键盘上获得确定按钮。如果知道会有多少行,例如设置一个小的 maxLength ,这是个好技巧。
    • 我想禁用 keyCode#66 可以吗?我该怎么做?
    • 为什么用 keyCode==66 代替 keyCode==EditorInfo.IME_ACTION_GO?
    【解决方案4】:

    要在 Kotlin 中执行此操作(还可以选择应用其他配置,例如 textCapSentences,您可以使用此扩展功能:

    // To use this, do NOT set inputType on the EditText in the layout
    fun EditText.setMultiLineCapSentencesAndDoneAction() {
        imeOptions = EditorInfo.IME_ACTION_DONE
        setRawInputType(InputType.TYPE_TEXT_FLAG_CAP_SENTENCES or InputType.TYPE_TEXT_FLAG_MULTI_LINE)
    }
    

    用法:

    myEditText.setMultiLineCapSentencesAndDoneAction()
    

    【讨论】:

    • 从 2019 年 6 月开始工作!谢谢:)
    • 对我来说关键是使用setRawInputType 而不是setInputType
    【解决方案5】:

    这似乎对我很有效

    int lineNum = 2;
    mEditText.setHorizontallyScrolling(false);
    mEditText.setLines(3);
    

    【讨论】:

      【解决方案6】:

      虽然其他解决方案都没有对我有用,但以下工作非常出色,并为我节省了日复一日的谷歌搜索,当然还有一些我自己的曲折。不幸的是,我不记得我是从哪里得到代码的,所以不能给作者他/她应得的荣誉。

      在你的 Java 代码中:

      ////////////Code to Hide SoftKeyboard on Enter (DONE) Press///////////////
      editText.setRawInputType(InputType.TYPE_CLASS_TEXT|InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD|InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
      editText.setImeActionLabel("DONE",EditorInfo.IME_ACTION_DONE);              //Set Return Carriage as "DONE"
      editText.setImeOptions(EditorInfo.IME_ACTION_DONE);
      
      editText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
          @Override
          public boolean onEditorAction(TextView v, int actionId, KeyEvent event) 
          {
                      if (event == null) {
                          if (actionId == EditorInfo.IME_ACTION_DONE) {
                              // Capture soft enters in a singleLine EditText that is the last EditText
                              // This one is useful for the new list case, when there are no existing ListItems
                              editText.clearFocus();
                              InputMethodManager inputMethodManager = (InputMethodManager)  getActivity().getSystemService(Activity.INPUT_METHOD_SERVICE);
                              inputMethodManager.hideSoftInputFromWindow(getActivity().getCurrentFocus().getWindowToken(), 0);
                          }
      
                          else if (actionId == EditorInfo.IME_ACTION_NEXT) {
                              // Capture soft enters in other singleLine EditTexts
                          } else if (actionId == EditorInfo.IME_ACTION_GO) {
                          } else {
                              // Let the system handle all other null KeyEvents
                              return false;
                          }
                      } 
              else if (actionId == EditorInfo.IME_NULL) {
                          // Capture most soft enters in multi-line EditTexts and all hard enters;
                          // They supply a zero actionId and a valid keyEvent rather than
                          // a non-zero actionId and a null event like the previous cases.
                          if (event.getAction() == KeyEvent.ACTION_DOWN) {
                              // We capture the event when the key is first pressed.
                          } else {
                              // We consume the event when the key is released.
                              return true;
                          }
                      } 
              else {
                          // We let the system handle it when the listener is triggered by something that
                          // wasn't an enter.
                          return false;
                      }
                      return true;
              }
      });
      
      【解决方案7】:

      使用

      editText.setImeOptions(EditorInfo.IME_ACTION_DONE);
      editText.setRawInputType(InputType.TYPE_CLASS_TEXT);
      

      在 XML 中:

      android:inputType="textMultiLine"
      

      【讨论】:

      • 效果很好...我很难找到它。此答案应标记为最佳答案
      • 为什么这个工作而不是全部设置在 xml 中?
      • 苦苦寻找这个信息。它仍然像魅力一样工作!
      • 只是程序所需的 rawInputType,您仍然可以从 xml 设置 imeOptions actionDone
      • 您也可以使用数据绑定从 XML 设置 rawInputType:@BindingAdapter("rawInputType") fun setRawInputType(view: EditText, inputType: Int) { view.setRawInputType(inputType) }。然后在您的布局 XML 的数据部分:&lt;import type="android.text.InputType" /&gt; 和您的 EditText app:rawInputType="@{InputType.TYPE_CLASS_TEXT}"
      【解决方案8】:

      来自 android 文档:'"textMultiLine" 普通文本键盘,允许用户输入包含换行符(回车)的长字符串。在键盘上。

      使用完成按钮获取多行(在本例中为 3 行)输入字段的简单方法是将 EditText 与

      android:lines="3" 
      android:scrollHorizontally="false" 
      

      但是,由于某种原因,这仅适用于我在代码中而不是布局文件(在 onCreate 中)中进行这些设置的情况

      TextView tv = (TextView)findViewById(R.id.editText);
      if (tv != null) {
          tv.setHorizontallyScrolling(false);
          tv.setLines(3);
      }
      

      我希望这对某人有所帮助,因为花了很长时间才弄清楚。如果您能从清单中找到使其工作的方法,请告诉我们。

      【讨论】:

      • 如果你想避免改变EditText的高度,我也建议尝试maxLines()而不是setLines()
      • 我认为在问题中没有明确说明您应该将 android:imeOptions 设置为 actionSend 之类的值。完成这个答案后,我必须设置 android:singleLine="true" ,即使 setMaxLines 会被代码覆盖(不这样做不会给你一个回车键,例如“发送”)。要捕获 操作,请检查来自stackoverflow.com/questions/5014219/… 的第一个答案。
      • 对不起,我找到的关于捕获 的最佳选择是@earlcasper 在这里回答stackoverflow.com/questions/1489852/…
      • 这对我来说非常有效(使用setMaxLines(3))非常感谢!
      • 像魅力一样工作:只需将 android:imeOptions="actionDone" android:inputType="text" 也添加到您的 XML 并删除 android:lines="3" android:scrollHorizo​​ntally="false"来自 XML
      【解决方案9】:

      工作解决方案在这里,创建您的自定义 EditTextView(只需扩展一个文本视图)并使用一段代码覆盖 onInputConnection,您可以在此处接受的答案中找到:Multiline EditText with Done SoftInput Action Label on 2.3

      【讨论】:

        【解决方案10】:

        我也挣扎了好久,终于找到了解决办法!

        只需创建一个自定义的 EditText 类:

        public class EditTextImeMultiline extends EditText {
        
            public void init() {
                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) {
                        for (int i = s.length(); i > 0; i--)
                            if (s.subSequence(i - 1, i).toString().equals("\n"))
                                s.replace(i - 1, i, "");
                    }
                });
                setSingleLine();
                setHorizontallyScrolling(false);
                this.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                    @Override
                    public void onGlobalLayout() {
                        EditTextImeMultiline.this.setLines(EditTextImeMultiline.this.getLineCount());
                    }
                });
            }
        
            public EditTextImeMultiline(Context context) {
                super(context);
                init();
            }
        
            public EditTextImeMultiline(Context context, AttributeSet attrs) {
                super(context, attrs);
                init();
            }
        
            public EditTextImeMultiline(Context context, AttributeSet attrs, int defStyleAttr) {
                super(context, attrs, defStyleAttr);
                init();
            }
        
            @TargetApi(Build.VERSION_CODES.LOLLIPOP)
            public EditTextImeMultiline(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
                super(context, attrs, defStyleAttr, defStyleRes);
                init();
            }
        }
        

        这个类删除了 lineBreaks (\n),像 textMultiline 一样包裹文本,并且允许你用 ImeAction 替换 Enter 按钮;)。

        你只需要在你的 XML 中调用它而不是经典的 EditText 类。

        这里解释一下逻辑:

        • 将 EditText 设置为 singleLine 以便能够显示 ImeAction 按钮而不是 Enter。
        • 移除水平滚动以使文本在到达视图末尾时转到下一行。
        • 使用onGlobalLayoutListener 观察布局变化,并将其“line”参数设置为editText 持有的当前文本的“lineCount”。这就是刷新它的高度。

        【讨论】:

          【解决方案11】:

          工作示例! 创建以下支持此功能的自定义 EditText 类并使用 xml 文件中的类。工作代码:

          package com.example;
          
          import android.content.Context;
          import android.util.AttributeSet;
          import android.view.inputmethod.EditorInfo;
          import android.view.inputmethod.InputConnection;
          import android.widget.EditText;
          
          public class ActionEditText extends EditText
          {
             public ActionEditText(Context context)
             {
                 super(context);
             }
          
             public ActionEditText(Context context, AttributeSet attrs)
             {
                 super(context, attrs);
             }
          
             public ActionEditText(Context context, AttributeSet attrs, int defStyle)
             {
                 super(context, attrs, defStyle);
             }
          
             @Override
             public InputConnection onCreateInputConnection(EditorInfo outAttrs)
             {
                 InputConnection conn = super.onCreateInputConnection(outAttrs);
                 outAttrs.imeOptions &= ~EditorInfo.IME_FLAG_NO_ENTER_ACTION;
                 return conn;
             }
          }
          
          <com.example.ActionEditText
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:imeOptions="actionDone"
                 android:inputType="textAutoCorrect|textCapSentences|textMultiLine" />
          

          【讨论】:

          • 这对我有用,我的要求是制作一个应该是多行的编辑文本,并且在软键上应该有下一步按钮...... .so 非常感谢我在编辑文本中添加了 2 行 android:inputType="textMultiLine" android:imeOptions="actionNext" 在上面的自定义类中我做了: InputConnection conn = super.onCreateInputConnection(outAttrs); //outAttrs.imeOptions &= ~EditorInfo.IME_FLAG_NO_ENTER_ACTION; outAttrs.imeOptions &= EditorInfo.IME_ACTION_NEXT;返回连接;
          • 有效。在 Andorid 6.0.1 上测试。
          【解决方案12】:

          解决这种情况的简单方法:

          • 在 EditText 上保留此属性:

            android:inputType="textMultiLine" 
            android:scrollHorizontally="false"
            
          • 然后添加此代码以仅在按下 ENTER 时隐藏键盘:

            editText.setOnEditorActionListener(new OnEditorActionListener() 
            {
                public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
                if (event.getKeyCode() == KeyEvent.KEYCODE_ENTER) 
                {
                    editText.setSelection(0);
                    InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
                    imm.hideSoftInputFromWindow(editText.getWindowToken(), 0);      
                    return true;
                 } 
                 else 
                 {
                    return false;
                 }
                 }
            });
            

          【讨论】:

            【解决方案13】:

            我在 4.x 上并尝试调用 setHorizo​​ntallyScrolling()(带或不带 setLine() 或 setMaxLines()),以及许多不同的 XML 配置以显示完成按钮。他们都没有工作。最重要的是,如果您的 EditText 是多行的,Android 将始终希望显示回车而不是“完成”按钮,除非您对此进行了一些修改。

            我发现不涉及重新映射回车行为的最简单的解决方案是:https://stackoverflow.com/a/12570003/3268329。此解决方案将使 Android 无情地希望强制为多行视图设置 IME_FLAG_NO_ENTER_ACTION 标志,这会导致完成按钮消失。

            【讨论】:

              【解决方案14】:

              如果您将输入选项 textImeMultiline 与 imeoptions flagnext 和 actionnext 一起使用,您将获得一个下一步按钮而不是回车符

              【讨论】:

                【解决方案15】:

                简短回答:不,我相信在 API 级别 11 (3.0) 之前这是不可能的。

                这里出现了同样的问题(在 cmets 中讨论了接受的答案):

                Android Soft keyboard action button

                来自最后的评论:

                查看我手机上的一些应用程序,多行框位于最后似乎很常见,其下方有一个可见的“完成”或“发送”按钮(例如电子邮件应用程序)。

                【讨论】:

                  【解决方案16】:

                  如果不是关于屏幕键盘的外观,您可以简单地在键盘上放置一个输入侦听器,并在用户输入换行符时触发“完成”状态。

                  【讨论】:

                    猜你喜欢
                    • 2011-06-28
                    • 1970-01-01
                    • 2019-06-02
                    • 1970-01-01
                    • 1970-01-01
                    • 2015-01-18
                    • 2013-11-22
                    • 1970-01-01
                    相关资源
                    最近更新 更多