如何实现带有“完成”按钮(而不是回车按钮)的多行EditText?

31

我有一个EditText用于输入邮件、短信等消息内容,我希望在用户点击“完成”按钮时立即发布该消息。我使用以下代码实现:

message.setOnEditorActionListener((textView, i, keyEvent) -> {
            switch (i) {
                case EditorInfo.IME_ACTION_DONE:
                    if (messageCanBePosted()) {
                        SoftKeyboard.hide(message);
                        postMessage();
                        return true;
                    } else {
                        return false;
                    }
                default:
                    return false;
            }
        }); 

但是我也希望这个消息框可以像其他通讯应用一样支持多行输入。可以通过添加以下代码实现:

android:inputType="textMultiLine"

问题是,添加这行代码后,ActionDone按钮开始像Enter按钮一样起作用。 因此,我用于捕获EditorInfo.IME_ACTION_DONE的回调永远不会被调用。 所以每次用户按下该按钮时,光标都会移动到新行而不是发布消息。

我如何保持EditText的多行行为(能够显示多行文本)和ActionDone按钮?

4个回答

56
使用
editText.setImeOptions(EditorInfo.IME_ACTION_DONE);
editText.setRawInputType(InputType.TYPE_CLASS_TEXT);

而在 XML 中:

android:inputType="textMultiLine"

来源: 带有“完成”按钮的多行EditText


1
只有这个对我起作用了,而且它的效果非常好——当EditText最初为空时,Done按钮会显示并工作,只有一行可见,并在用户输入或从代码(setText)中最初添加更多文本时扩展到更多行。 - javaxian
8
应该注明出处才更好:https://dev59.com/iXA75IYBdhLWcg3w_uqD#41022589 - logi-kal
1
谢谢,经过几个小时的搜索,你是对的,仅仅改变XML是不起作用的。真是一团糟... - anni
1
终于成功了!对我来说,这就像魔法一样,多年以来一直被这个可怕的 XML EditText 属性困扰着! - Pelanes
2
对于多行URL文本输入字段,以下是我使用的方法:editText.setRawInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_URI); editText.setImeOptions(EditorInfo.IME_ACTION_DONE);,您不需要在EditText XML属性中指定任何内容。一些键盘会根据此InputType显示Web地址的建议或显示“.com”键。 - Mr-IDE

37

最终,在这里搜寻相似线程后,我找到了解决方案。只需要在您的活动/片段中添加这些行:

editText.setHorizontallyScrolling(false);
editText.setMaxLines(Integer.MAX_VALUE);

由于某些原因,如果您从XML应用完全相同的设置,则无法正常工作。您应该以编程方式执行它。

还有另一个可能的解决方案-从EditText派生并手动应用 EditorInfo.IME_ACTION_DONE 。但对我来说,第一个解决方案看起来更简单。


@silverFox 是的,对我有效。你在xml中为你的EditText定义了哪些属性? - Ruslan
太棒了。我已经试了好几天,觉得这是不可能的。谢谢! - Monte Creasor
终于!从EditText派生并手动应用DONE使editText表现出奇怪的行为(失去焦点忽略设置文本..魔法..)这个简单的解决方案像魔法一样奏效。 - Aetherna
这个答案 + editText.setRawInputType(InputType.TYPE_CLASS_TEXT) 对我有用。在我的情况下,我还在xml中使用了digits字段(https://dev59.com/KHE95IYBdhLWcg3wUcRn)。 - Himanshu Mori

20

继续 Ruslan 的回答。这个技巧很有用,但在 XML 中还有一件事情需要注意。

EditText 应该具有输入类型 text,否则 actionDone 将无法工作。 EditText 的默认输入类型允许用户输入换行符,因此应将 inputType 设置为 text,即:

android:inputType="text"
//And of course
android:imeOptions="actionDone"

在你的Java类中,你需要添加:

editText.setHorizontallyScrolling(false);

2
在XML中,inputType=text & imeOptions=actionDone,而在代码中使用setHorizontallyScrolling()实现了它!谢谢,终于搞定了。 - Borzh

0

可重用的 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) {
    inputType = EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE
    horizontalScroll(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()

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