Multiline EditText with Done SoftInput Action Label on 2.3
Asked Answered
W

7

83

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
Wakerly answered 16/2, 2011 at 8:38 Comment(0)
W
164

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.

Wakerly answered 18/2, 2011 at 4:5 Comment(6)
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. :-)Adscription
+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. @Wakerly many thanks for the solution.Kuehl
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?Monah
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.Araminta
@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.Lorola
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;Rn
A
108

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" />
Aftermath answered 16/2, 2011 at 8:39 Comment(14)
Timmmm, is this tested on 2.3?Wakerly
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.Wakerly
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.Aftermath
I tried this on 2.3 (and 4.x), and it worked for my application.Expeditionary
This is nice answer. Thank you. Does this mean, there is no way to have "newline enter button" along with done button?Relations
@matej.smitala Yeah, you can't have both.Aftermath
I like this option more than the "accepted" answer, because it works with actionDone AND actionNext (and probably most any other action)Page
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.Matelda
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?Araminta
Replace your EditText with the XML given in the question.Aftermath
This works but there is no cursor, so I set android:textCursorDrawable="@null" and everything works great!Clipboard
after some failed solutions, I can confirm that this one worked on a KitKat Samsung Galaxy SIII. +1Enchanting
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 :)Felike
Nine years into the future, this still works like a charm on SDK 30 💪Corriveau
K
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.

Kuo answered 26/11, 2012 at 11:31 Comment(6)
@Kuo : 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!Astringent
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.Shoshana
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).Shoshana
works very well. This is a good example of improving on an old answer!!Bickering
Working for me on a Galaxy S5 running Lollipop. Great solution. Strange that setting scroll horizontally in xml does not have the same effectAssuntaassur
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.Angele
C
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"/> 
Calie answered 5/11, 2015 at 0:6 Comment(0)
S
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.

Seedling answered 9/12, 2015 at 19:21 Comment(0)
P
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.

Photocell answered 26/5, 2011 at 19:56 Comment(4)
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.Wakerly
@Mullins: Did you add your own "done" button into the SoftInput Keyboard? How did you do that while keeping the "Enter"?Glowing
Nope. I created a done button on the UI separate to the keyboard.Photocell
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.Aftermath
A
-1

Use these attribute in your XML.

android:inputType="textImeMultiLine"

android:imeOptions="actionDone"

Allan answered 7/11, 2017 at 4:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.