带有完成操作按钮的多行输入框

145

是否可以同时设置 android:inputType="textMultiLine"android:imeOptions="actionDone" 属性来创建一个多行文本框,并让键盘上的操作按钮显示“完成”而不是“回车”(Enter)?

我想要一个多行编辑框,并希望键盘上的操作按钮是“完成”,而不是“回车”(Carriage Return),但似乎无法实现。


尝试使用多行EditText和Button组合在一起的复合小部件怎么样? - C--
1
请将以下与编程有关的内容从英语翻译成中文。仅返回已翻译的文本:类似于https://dev59.com/PW445IYBdhLWcg3wJ298 - larham1
17个回答

264

使用

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

以及在XML中:

android:inputType="textMultiLine"

1
非常好用...我曾经苦苦寻找。这个答案应该标记为最佳答案。 - MFAL
10
为何使用这种方法而不是在XML中设置所有内容? - Andrew Steinmetz
1
有点费劲才找到这个信息。但它仍然完美地工作着! - Costin
6
你只需要以编程方式提供所需的原始输入类型,但仍然可以从XML设置imeOptions为“actionDone”。 - hmac
2
您可以使用数据绑定从XML设置rawInputType:@BindingAdapter("rawInputType") fun setRawInputType(view: EditText, inputType: Int) { view.setRawInputType(inputType) }。然后在布局XML的数据部分中:<import type="android.text.InputType" />,并在EditText中使用app:rawInputType="@{InputType.TYPE_CLASS_TEXT}" - ubuntudroid
显示剩余8条评论

53

根据Android文档: '"textMultiLine" 正常的文本键盘,允许用户输入包含换行符(回车)的长文本字符串。' 因此,如果你想要在键盘上有 '完成' 按钮,则 textMultiLine 属性不适用。

一个简单的方法来获得带有 '完成' 按钮的多行(3行)输入字段是使用 EditText

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

然而,由于某些原因,只有我在代码中进行这些设置(在onCreate方法中)时才有效,而不是在布局文件中进行设置。

Translated:

然而,由于某些原因,只有我在代码中进行这些设置(在onCreate方法中)时才有效,而不是在布局文件中进行设置。

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

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


4
如果你想避免改变“EditText”的高度,我建议你尝试使用maxLines()而不是setLines() - Daniel Smith
我认为问题中没有明确说明您应该使用像actionSend这样的值设置android:imeOptions。补充一下这个答案,即使通过代码设置setMaxLines会覆盖它,我也必须将android:singleLine =“true”设置为真(不这样做不会给您一个例如“发送”的回车键)。要捕获<Enter>操作,请查看https://dev59.com/PW445IYBdhLWcg3wJ298的第一个答案。 - DNax
抱歉,我找到的关于捕获<Enter>的最佳替代方法是@earlcasper在这里给出的答案https://dev59.com/y3I_5IYBdhLWcg3wMf5_。 - DNax
1
这对我来说完美地运作了(使用 setMaxLines(3))。非常感谢! - laurencevs
对我有用,使用 setMaxLines() 并将 lines 设为 1。非常感谢! - Dooskington
1
像魔术一样运行:只需在您的XML中添加android:imeOptions="actionDone"和android:inputType="text",同时从XML中删除android:lines="3"和android:scrollHorizontally="false"。 - HannahCarney

29

工作示例! 创建以下自定义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" />

这对我有用,我的要求是制作一个编辑文本框,它应该是多行的,并且软键盘上应该有下一个按钮...............非常感谢。我所做的是在编辑文本框中添加了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; return conn; - yash
可以工作。已在Android 6.0.1上进行了测试。 - AmiguelS

20

要在 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()

1
截至2019年6月仍然有效!谢谢 :) - Rohan Taneja
1
对我来说关键是使用 setRawInputType 而不是 setInputType - Tamoxin

13

可重用的 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()

需要在回调函数中轻松控制键盘?阅读此文章

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


2
☝️这是一个很棒的答案。 - Michael

10

我认为这是做你的事情的方法。使用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;
        }
});

1
使用固定数量的最大数字与 android:lines="10" 对我有用,可以在键盘上获得“确定”按钮。如果知道将有多少行,例如设置了较小的 maxLength,则这是一个好技巧。 - sunadorer
我想禁用keyCode#66,这可能吗?我该怎么做? - Adil Malik
1
为什么要使用keyCode==66而不是keyCode == EditorInfo.IME_ACTION_GO? - tse

5

这对我来说似乎完美地运作了

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

3
这种情况的简单解决方法是:
  • keep this attributes on the EditText:

    android:inputType="textMultiLine" 
    android:scrollHorizontally="false"
    
  • then add this code to only hide the keyboard when ENTER is pressed:

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

3
简短回答:不,我认为在API级别11(3.0)之前不可能实现。
同样的问题在这里出现了(在被接受的答案的评论中讨论): Android软键盘操作按钮 从最后一条评论中可以看出:
查看手机上的一些应用程序,似乎将多行框放在最后很常见,并在其下方显示一个可见的“完成”或“发送”按钮(例如,电子邮件应用)。

2

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接