31

I have EditText which is used for entering contents on messages (emails, sms). I want message to be immediately posted on ActionDone button click. I use following code for this:

message.setOnEditorActionListener((textView, i, keyEvent) -> {
            switch (i) {
                case EditorInfo.IME_ACTION_DONE:
                    if (messageCanBePosted()) {
                        SoftKeyboard.hide(message);
                        postMessage();
                        return true;
                    } else {
                        return false;
                    }
                default:
                    return false;
            }
        }); 

But also I want this message field to be multiline, like in any other messenger apps. I can achieve it with this line:

android:inputType="textMultiLine"

The problem is that after adding this line ActionDone button starts acting like Enter button. So my callback for catching EditorInfo.IME_ACTION_DONE is never called. So each time user press that button cursor moves to new line instead of posting message.

How can I keep both multiline behavior of EditText (ability to show text on multiple lines) and ActionDone button?

Ruslan
  • 1,039
  • 1
  • 9
  • 16

4 Answers4

56

Use

editText.setImeOptions(EditorInfo.IME_ACTION_DONE);
editText.setRawInputType(InputType.TYPE_CLASS_TEXT);

and in XML:

android:inputType="textMultiLine"

Source : Multi-line EditText with Done action button

Rathi J
  • 849
  • 9
  • 16
  • 1
    Only this one worked for me, and it worked like a charm - the Done button displayed & working, only a single line visible when an EditText is initially empty, and expanding to more lines when a user types in OR there's more text added initially from the code (setText). – javaxian Apr 26 '17 at 20:00
  • 8
    It would have been nice to cite the source: http://stackoverflow.com/a/41022589/4607733 – logi-kal May 09 '17 at 14:19
  • 1
    Thanks, after searching for hours, you were right, it does not work only by changing xml. What a mess... – anni Jan 14 '18 at 14:44
  • 1
    At last, worked! This is magic for me, years and years with this horrible bug in xml EditText properties! – Pelanes Feb 09 '18 at 08:15
  • 2
    For multi-line URL text entry fields, this is what worked for me: `editText.setRawInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_URI); editText.setImeOptions(EditorInfo.IME_ACTION_DONE);` and you don't need to specify anything in the EditText XML properties. Some keyboards adapt to this InputType by showing suggestions of web addresses, or displaying a ".com" key. – Mr-IDE Aug 11 '18 at 12:21
36

Finally, after searching here for similar threads I have found solution. Just need to add these lines on your Activity/Fragment:

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

For some reason it doesn't work if you apply exact same setting from xml. You should do it programmatically.

There is also another possible solution - derive from EditText and apply EditorInfo.IME_ACTION_DONE manually. But for me first solution looks simpler.

Ruslan
  • 1,039
  • 1
  • 9
  • 16
  • @silverFox yep, it worked for me. Which properties do you define for your EditText in xml? – Ruslan Sep 15 '16 at 22:19
  • Absolutely brilliant. I've been trying to do this for days and thought it was impossible. Thanks! – Monte Creasor Feb 25 '17 at 21:59
  • Finally! Deriving from EditText and applying DONE manually caused the editText to behave weirdly (loosing focus ignoring set text.. magic...) This simple solution worked like a charm. – Aetherna Jan 15 '18 at 16:09
  • this answer + editText.setRawInputType(InputType.TYPE_CLASS_TEXT) worked for me.. and in specific my case I also use digits field in xml (https://stackoverflow.com/questions/2361497/how-to-create-edittext-accepts-alphabets-only-in-android) – Himanshu Mori Feb 12 '19 at 18:41
20

Continuing Ruslan's answer. The trick worked but there is one more thing that you need to take care of in XML.

EditText should have input type text otherwise actionDone won't work. Default input type of EditText does allow user to input line breaks so inputType should be set to text i.e.

android:inputType="text"
//And of course
android:imeOptions="actionDone"

And in your java class you need to add:

editText.setHorizontallyScrolling(false);
Borzh
  • 5,069
  • 2
  • 48
  • 64
Noman Rafique
  • 3,735
  • 26
  • 29
  • 2
    inputType=text & imeOptions=actionDone in xml and setHorizontallyScrolling() in the code did it! Thanks, at last. – Borzh Dec 14 '17 at 19:52
0

Reuseable Kotlin Solution

Setting these values in code worked for me, thanks to the other answers

edittext.inputType = EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE
edittext.setHorizontallyScrolling(false)
edittext.maxLines = Integer.MAX_VALUE // Or your preferred fixed value

I require this frequently, so made this to keep the code clean:

fun EditText.multilineIme(action: Int) {
    inputType = EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE
    horizontalScroll(false)
    maxLines = Integer.MAX_VALUE
}

// Then just call
edittext.multilineIme(EditorInfo.IME_ACTION_DONE)

If you want to be add an optional custom action on 'Done', try this:

fun EditText.multilineDone(callback: (() -> Unit) = null) {
    val action = EditorInfo.IME_ACTION_DONE
    multilineIme(action)
    setOnEditorActionListener { _, actionId, _ ->
            if (action == actionId) {
                callback?.invoke()
                true
            }
            false
        }
    }
}

// Then you can call
edittext.multilineDone { closeKeyboard() }

// or just
edittext.multilineDone()
Gibolt
  • 42,564
  • 15
  • 187
  • 127