2.3版本上具有Done SoftInput动作标签的多行EditText

82
有没有办法在Android 2.3上使用多行 EditText 并显示IME Action标签“完成”?在Android 2.2中,这不是问题,回车键显示IME动作标签“完成”(android:imeActionLabel="actionDone"),并在单击时关闭软输入。但是,在为多行配置EditText时,Android 2.3删除了显示“完成”操作的能力。我已经通过使用KeyListener来修改软输入回车键的行为,但回车键仍然看起来像回车键。以下是EditText的声明:
<EditText
        android:id="@+id/Comment"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:layout_marginBottom="0dp"
        android:lines="3"
        android:maxLines="3"
        android:minLines="3"
        android:maxLength="60"
        android:scrollHorizontally="false"
        android:hint="hint"
        android:gravity="top|left"
        android:textColor="#888"
        android:textSize="14dp"
        />
<!-- android:inputType="text" will kill the multiline on 2.3! -->
<!-- android:imeOptions="actionDone" switches to a "t9" like soft input -->

在将内容视图设置到活动中后,当我检查inputType的值时,会显示为:

inputType = 0x20001

以下是:

  • class = TYPE_CLASS_TEXT | TYPE_TEXT_VARIATION_NORMAL
  • flags = InputType.TYPE_TEXT_FLAG_MULTI_LINE
7个回答

164

在仔细阅读了 TextViewEditorInfo 的文档之后,我发现平台将强制在多行文本视图上使用 IME_FLAG_NO_ENTER_ACTION

请注意,TextView 会自动为您在多行文本视图上设置此标志。

我的解决方案是子类化 EditText,在让平台配置完它们后调整 IME 选项:

@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
    InputConnection connection = super.onCreateInputConnection(outAttrs);
    int imeActions = outAttrs.imeOptions&EditorInfo.IME_MASK_ACTION;
    if ((imeActions&EditorInfo.IME_ACTION_DONE) != 0) {
        // clear the existing action
        outAttrs.imeOptions ^= imeActions;
        // set the DONE action
        outAttrs.imeOptions |= EditorInfo.IME_ACTION_DONE;
    }
    if ((outAttrs.imeOptions&EditorInfo.IME_FLAG_NO_ENTER_ACTION) != 0) {
        outAttrs.imeOptions &= ~EditorInfo.IME_FLAG_NO_ENTER_ACTION;
    }
    return connection;
}
在上面的代码中,我强制使用了 IME_ACTION_DONE,尽管这可以通过繁琐的布局配置来实现。

25
我通常不会给出像“哇,谢谢”的泛泛而谈的评论,但这个答案确实足够有帮助且没有得到足够的赞赏,所以我认为它值得被认可。总之,哇,谢谢。 :-) - plowman
3
对于你的回答表示赞同,但如果你在代码中设置EditText的输入类型,会出现问题:它会移除垂直滚动并添加水平滚动。为了解决这个问题,请使用以下代码:editTextObj.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_CAP_SENTENCES | InputType.TYPE_TEXT_FLAG_MULTI_LINE);通常会发生这种情况,如果你在多个布局中重复使用相同的视图。@ohhorob 非常感谢你提供的解决方案。 - Jayshil Dave
2
它运行得非常好!但我真的不太理解这段代码。你有什么地方可以让我了解整个标志机制吗? - vanleeuwenbram
谢谢,我是一个初学者,我把这个放在使用对话框EditText的活动中,所以它不在我的活动XML文件中。我尝试将这段代码放入我的活动中,但出现了一个错误:The method onCreateInputConnection(EditorInfo) of type SMSMain must override or implement a supertype method。您在开头调用了super,所以不确定问题出在哪里。您有什么建议吗?谢谢。 - Azurespot
@NoniA,你需要创建一个EditText的子类。在这个子类中调用该方法。创建一个继承自EditText的类,并将该方法放入该类中。 - Shah
难道这样不更容易吗:outAttrs.imeOptions &= ~EditorInfo.IME_MASK_ACTION; outAttrs.imeOptions |= EditorInfo.IME_ACTION_DONE; outAttrs.imeOptions &= ~EditorInfo.IME_FLAG_NO_ENTER_ACTION; - mdubez

107

Ohhorob的回答基本上是正确的,但他的代码实在是冗余了!其实这个简单得多的版本(完整的代码适合懒惰读者)与他的代码基本等效:

package com.example.views;

import android.content.Context;
import android.util.AttributeSet;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.widget.EditText;

// An EditText that lets you use actions ("Done", "Go", etc.) on multi-line edits.
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;
    }
}

请注意,某些inputType选项(如textShortMessage)无法使用此方法!我建议您首先使用inputType="text"。以下是您可以在XML中使用它的方式。

<com.example.views.ActionEditText
    android:id=...
    android:layout_stuff=...
    android:imeOptions="actionDone"
    android:inputType="textAutoCorrect|textCapSentences|textMultiLine"
    android:maxLines="3" />

1
如果您的代码适用于 2.3 版本,那么我的也应该适用。它们非常相似,并且我是基于您的代码编写的,所以谢谢!在 2.3 版本中是否有不同于 4.0 版本的特殊性?多行编辑上的“无操作”标准是 Google 添加的有意行为。 - Timmmm
5
我在2.3(和4.x)上试过这个方法,并且对我的应用程序有效。 - mlc
2
@matej.smitala 是的,你不能两者兼得。 - Timmmm
1
经过数小时的寻找最佳解决方案,这似乎是实现多行编辑文本而无需回车键的最佳且最简单的方法。 - micnguyen
2
九年后,这在SDK 30上仍然像魔法一样运行良好。 - Ambran
显示剩余10条评论

56

EditText类的替代解决方案是通过以下配置来配置您的EditText实例:

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

至少在 Android 4.0 上,这对我有效。它配置 EditText 实例,以便用户编辑单行字符串,即使设置了 IME 操作,也会以软换行的方式在多行上显示。


2
@Futzilogik:您,先生,应该得到更多的赞!这个答案真是救了我一命,而且还很简单。我的意思是,哇塞。我希望我可以投多次赞。非常感谢! - Swayam
3
我正在使用4.4.2版本,但这种方法对我没有用或者说我使用的方式不对。我只在XML文件中配置了它,所以可能存在问题。我将输入类型(inputType)配置为"textEmailAddress|textMultiLine",水平滚动(scrollHorizontally)设为false,maxLines(xml文件中的最大行数)设为500,singleLine设为false,imeOptions设为actionNext。我尝试将输入类型中的"textMultiLine"去掉。如果加上"textMultiLine",键盘会有回车键,而去掉它后,所有内容都在同一行并且仍然会水平滚动。这似乎是最简单的解决方案,但上面那个方法对我有效,所以现在就采用它。 - reactive-core
6
关于我之前的评论(无法编辑),怀疑是没有设置MAX_VALUE或在创建EditText后更改了这些设置的问题,我按照这里指示的代码尝试了一下,成功了!我只是想为其他人发布一下,你无法在XML中完成它(至少我做不到)。我还有其他设置:singleLine=false,imeOptions=actionNext,inputType=textEmailAddress(无多行)。 - reactive-core
运作非常好。这是改进旧答案的一个很好的例子!! - nPn
在我的运行Lollipop的Galaxy S5上工作良好。是个好的解决方案。奇怪的是,在xml中设置水平滚动并没有产生相同的效果。 - Scott Birksted
只有在XML中设置了inputType,此方法才有效。如果没有设置inputType,则会触发输入操作。 - CodyEngel

6

以下是之前的回答

public class MultiLineText extends EditText {

    public MultiLineText(Context context) {
        super(context);
    }

    public MultiLineText(Context context, AttributeSet attrs) {
        super(context, attrs);

    }

    public MultiLineText(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);

    }

    @Override
    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
        InputConnection connection = super.onCreateInputConnection(outAttrs);
        int imeActions = outAttrs.imeOptions&EditorInfo.IME_MASK_ACTION;
        if ((imeActions&EditorInfo.IME_ACTION_DONE) != 0) {
            // clear the existing action
            outAttrs.imeOptions ^= imeActions;
            // set the DONE action
            outAttrs.imeOptions |= EditorInfo.IME_ACTION_DONE;
        }
        if ((outAttrs.imeOptions&EditorInfo.IME_FLAG_NO_ENTER_ACTION) != 0) {
            outAttrs.imeOptions &= ~EditorInfo.IME_FLAG_NO_ENTER_ACTION;
        }
        return connection;
    }
}

使用方式如下:

<myapp.commun.MultiLineText
  android:id="@+id/textNotes"
  android:layout_height="wrap_content"
  android:minHeight="100dp"
  android:layout_width="wrap_content"
  android:hint="Notes"
  android:textSize="20sp"
  android:padding="7dp"
  android:maxLines="4"/> 

6

如果要将操作标记为已完成,可以使用:

XML

android:inputType="text|textCapSentences"    

JAVA

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

希望这对您有用。


1

显然,对于原始问题的答案是肯定的,但我相信Android团队正在努力让开发人员思考一下如何使用多行EditText。他们希望回车键添加换行符,并且可能期望您提供一个按钮或另一种输入方式来触发您完成编辑的事件。

我有同样的问题,我的明显解决方案只是添加一个完成按钮,让回车按钮添加换行符。


抱歉,我的问题可能没有表达清楚。多行是为了软换行单行输入。即不允许使用换行符。 - ohhorob
@Mullins:你在软键盘中添加了自己的“完成”按钮吗?你是如何保留“Enter”键的同时实现这一点的? - avepr
不是的。我在UI上创建了一个独立于键盘的“完成”按钮。 - Mullins
1
也许安卓团队应该听从自己的建议,在消息应用程序中的多行文本编辑器的操作按钮上创建新行而不是发送消息。 - Timmmm

-1

在你的XML中使用这些属性。

android:inputType="textImeMultiLine"

android:imeOptions="actionDone"


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