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:
TYPE_CLASS_TEXT | TYPE_TEXT_VARIATION_NORMAL
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"/>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With