82

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
ohhorob
  • 11,695
  • 7
  • 41
  • 50

7 Answers7

163

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
  • 11,695
  • 7
  • 41
  • 50
  • 24
    I don't usually give generic comments like 'omg thanks' but this answer was sufficiently helpful and unappreciated that I thought it deserved recognition. In summary, omg thanks. :-) – plowman Mar 07 '11 at 04:10
  • 3
    +1 for the answer but if you setting an input type of a edittext from code in this case. It removes the vertical scroll and adds horizontal scroll. To solve that issue use below code. editTextObj.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_CAP_SENTENCES | InputType.TYPE_TEXT_FLAG_MULTI_LINE); Can generally happen if you are reusing a view by including the same in multiple layouts. @ohhorob many thanks for the solution. – Jayshil Dave Jan 02 '12 at 15:56
  • 2
    It works like a charm! But I don't really understand the code. You got some place where I can read about the whole flag mechanism? – vanleeuwenbram Jan 18 '13 at 10:29
  • Thanks, I am a beginner, I put this in my activity that uses a dialog box `EditText`, so it is not in my activity xml. I tried putting this code in my activity, but got an error: `The method onCreateInputConnection(EditorInfo) of type SMSMain must override or implement a supertype method`. You call `super` in the beginning, so not sure what is the problem. You have any suggestions? Thanks. – Azurespot Jan 01 '15 at 07:37
  • @NoniA. you have to make subclass of EditText. and in that class you have to call this method. create a class that extends to EditText. and put that method in that class. – Shah Feb 06 '15 at 09:25
  • Isn't it easier to do: `outAttrs.imeOptions &= ~EditorInfo.IME_MASK_ACTION; outAttrs.imeOptions |= EditorInfo.IME_ACTION_DONE; outAttrs.imeOptions &= ~EditorInfo.IME_FLAG_NO_ENTER_ACTION;` – mdubez Jun 22 '16 at 20:17
106

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" />
Timmmm
  • 88,195
  • 71
  • 364
  • 509
  • Timmmm, is this tested on 2.3? – ohhorob Sep 24 '12 at 18:22
  • Just that the whole question is specifically about 2.3. The idiosyncrasies of 2.3 pushed me to do it this way. Nice to see it has improved somewhat. – ohhorob Sep 25 '12 at 15:38
  • 1
    If your code works on 2.3, so should mine. They are very nearly the same, and I based mine or your code, so thanks! Are there idiosyncrasies of 2.3 that aren't in 4.0? The standard "no actions on multiline edits" is deliberate behaviour added by Google. – Timmmm Sep 25 '12 at 16:33
  • 5
    I tried this on 2.3 (and 4.x), and it worked for my application. – mlc Oct 08 '12 at 22:36
  • This is nice answer. Thank you. Does this mean, there is no way to have "newline enter button" along with done button? – hendrix Dec 05 '12 at 16:52
  • 2
    @matej.smitala Yeah, you can't have both. – Timmmm Dec 06 '12 at 11:20
  • Works like a charm! Thanks @Timmmm and ohhorob. – kpsfoo Jun 01 '14 at 14:22
  • I like this option more than the "accepted" answer, because it works with actionDone AND actionNext (and probably most any other action) – Kyle Jahnke Oct 08 '14 at 13:15
  • 1
    After hours of searching for the best solution, this seems like the best & simplest way of achieving a multi-line edit text without the enter key. – micnguyen Nov 28 '14 at 04:40
  • Sorry, I'm a beginner... how do you connect this code with your EditText in xml? I create the inner class, but it says it's unused in my IDE. But how would I use it? – Azurespot Feb 05 '15 at 03:11
  • Replace your `EditText` with the XML given in the question. – Timmmm Feb 05 '15 at 08:11
  • This works but there is no cursor, so I set android:textCursorDrawable="@null" and everything works great! – Philip Herbert Jun 25 '15 at 10:39
  • after some failed solutions, I can confirm that this one worked on a KitKat Samsung Galaxy SIII. +1 – voghDev Sep 28 '15 at 07:19
  • works on 6.x too. im always glad when i encounter a problem due to the default android limitations and then find a alrdy posted solution on SO :) – MojioMS Jul 04 '16 at 21:03
  • 2
    Nine years into the future, this still works like a charm on SDK 30 – Ambran Nov 17 '21 at 11:38
56

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.

Futzilogik
  • 931
  • 7
  • 5
  • 2
    @Futzilogik : You,sir, deserve much more upvotes! This answer was a life saver, and a simple one too. I mean, omg wow. I wish I could upvote more than once. Much thanks! – Swayam Jan 30 '14 at 05:31
  • 3
    I'm running 4.4.2, and this didn't work for me or at least my way of doing it. I did it in XML only, so maybe that's a problem. I configured the inputType to "textEmailAddress|textMultiLine," scrollHorizontally to false, maxLines to 500 (xml file), singleLine to false, and imeOptions to actionNext. I tried removing "textMultiLine" from the inputtype. With textMultiLine, I get the ENTER key on the keyboard, and without it, everything stays on a single line and still scrolls horizontally. This did seem like the easiest solution, but the one above works for me, so going with it for now. – reactive-core May 19 '14 at 16:39
  • 6
    Regarding my previous comment (unable to edit it), suspecting it was either an issue with not setting MAX_VALUE or just changing these after the edittext was created, I tried in code as indicated here, and it works! I just wanted to post for others, you can't do it in XML (or I couldn't anyway). Other settings I have: singleLine=false, imeOptions=actionNext, inputType=textEmailAddress (no multiline). – reactive-core May 19 '14 at 16:58
  • works very well. This is a good example of improving on an old answer!! – nPn Sep 16 '14 at 02:05
  • Working for me on a Galaxy S5 running Lollipop. Great solution. Strange that setting scroll horizontally in xml does not have the same effect – Scott Birksted Jun 10 '16 at 15:49
  • This only works if you set an inputType in XML, if you don't set the inputType then it will give you the enter action. – CodyEngel Apr 13 '17 at 15:21
6

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"/> 
user3525689
  • 191
  • 3
  • 3
6

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.

Alex Zaraos
  • 6,443
  • 2
  • 26
  • 21
1

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.

Mullins
  • 2,304
  • 1
  • 19
  • 18
  • Sorry, I may not have been clear enough with my question.. the multiple lines is for soft-wrapping a single-line input. i.e. new-line characters are not allowed. – ohhorob May 26 '11 at 20:35
  • @Mullins: Did you add your own "done" button into the SoftInput Keyboard? How did you do that while keeping the "Enter"? – avepr Feb 07 '12 at 08:01
  • Nope. I created a done button on the UI separate to the keyboard. – Mullins Feb 08 '12 at 09:52
  • 1
    Well maybe the Android team should follow their own advice and make the action button of the multiline TextEdit in the messaging app create newlines instead of sending the message. – Timmmm Sep 24 '12 at 16:47
-1

Use these attribute in your XML.

android:inputType="textImeMultiLine"

android:imeOptions="actionDone"

Community
  • 1
  • 1
Gaurav Kumar
  • 834
  • 1
  • 6
  • 14