Multiline EditText with Done SoftInput Action Label on 2.3
Is there a way to have a Multi-Line EditText
present and use the IME Action Label "Done" on Android 2.3?
In Android 2.2 this is not a problem, the enter button shows the IME Action Label "Done" (android:imeActionLabel="actionDone"
), and dismisses Soft Input when clicked.
When configuring an EditText
for multi-line, Android 2.3 removes the ability to show the "Done" action for the Soft Input keyboard.
I have managed to alter the behaviour of the Soft Input enter button by using a KeyListener
, however the enter button still looks like an enter key.
Here is the declaration of the 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 -->
When I check the inputType
value after loading setting the content view in the activity, it shows up as:
inputType = 0x20001
Which is:
- class =
TYPE_CLASS_TEXT | TYPE_TEXT_VARIATION_NORMAL
- flags =
InputType.TYPE_TEXT_FLAG_MULTI_LINE
Well, after re-reading the TextView
and EditorInfo
docs, it has become clear that the platform is going to force IME_FLAG_NO_ENTER_ACTION
for multi-line text views.
Note that
TextView
will automatically set this flag for you on multi-line text views.
My solution is to subclass EditText
and adjust the IME options after letting the platform configure them:
@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;
}
In the above, I'm forcing IME_ACTION_DONE
too, even though that can be achieved through tedious layout configuration.
Ohhorob's answer is basically correct, but his code is really really redundant! It is basically equivalent to this much simpler version (full code for lazy readers):
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;
}
}
Note that some inputType
options such as textShortMessage
make this not work! I suggest you start with inputType="text"
. Here is how you could use it in your XML.
<com.example.views.ActionEditText
android:id=...
android:layout_stuff=...
android:imeOptions="actionDone"
android:inputType="textAutoCorrect|textCapSentences|textMultiLine"
android:maxLines="3" />
An alternative solution to subclassing the EditText class is to configure your EditText instance with this:
editText.setHorizontallyScrolling(false);
editText.setMaxLines(Integer.MAX_VALUE);
At least, this works for me on Android 4.0. It configures the EditText instance so that the user edits a single-line string that is displayed with soft-wrapping on multiple lines, even if an IME action is set.
Following previous answer
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;
}
}
Use this like
<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"/>
for put the action Done, you could use:
XML
android:inputType="text|textCapSentences"
JAVA
editText.setHorizontallyScrolling(false);
editText.setMaxLines(Integer.MAX_VALUE);
I hope its work for you.
Apparently the answer to the original question is Yes but I believe the Android team are trying to make developers think a little bit about how they use the multi-line EditText. They want the enter key to add newlines and probably expect that you provide a button or another input means to raise the event that you are done editing.
I have the same issue and my obvious solution was simply to add a done button and let the enter button add the newlines.
Use these attribute in your XML.
android:inputType="textImeMultiLine"
android:imeOptions="actionDone"
精彩评论