Mehrzeiliger EditText mit der Aktionstaste Fertig

114

Ist es möglich, ein EditTextWidget mit android:inputType="textMultiLine"set zu haben und android:imeOptions="actionDone"gleichzeitig?

Ich möchte ein mehrzeiliges Bearbeitungsfeld, bei dem die Aktionstaste auf der Tastatur fertig ist und nicht die Eingabetaste (Wagenrücklauf), aber es scheint nicht zu funktionieren.

Danke im Voraus

kefs
quelle
Wie wäre es mit einem zusammengesetzten Widget mit mehrzeiligem EditText und einer Schaltfläche zusammen?
Subin Sebastian

Antworten:

194

Verwenden

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

und in XML:

android:inputType="textMultiLine"
alexbtr
quelle
für mich würde der Cursor immer noch textField.setCursorVisible(false);onEditorActionListener
anzeigen
Funktioniert mit 4.2.2 und 7.1.1. Vielen Dank.
Tehcpu
1
Funktioniert sehr gut ... Ich hatte Mühe, es zu finden. Diese Antwort sollte als beste Antwort markiert werden
MFAL
7
Warum funktioniert dies im Gegensatz zum Einrichten in XML?
Andrew Steinmetz
1
Kämpfte ein wenig, um diese Informationen zu finden. Es funktioniert immer noch wie ein Zauber!
Costin
51

Aus der Android-Dokumentation: ' "textMultiLine" Normale Texttastatur, mit der Benutzer lange Textzeichenfolgen eingeben können, die Zeilenumbrüche enthalten (Zeilenumbrüche) . 'Daher ist das textMultiLine-Attribut nicht geeignet, wenn Sie die Schaltfläche' Fertig 'auf der Tastatur haben möchten.

Eine einfache Möglichkeit, ein mehrzeiliges (in diesem Fall 3 Zeilen) Eingabefeld mit der Schaltfläche "Fertig" abzurufen, ist die Verwendung von "EditText" mit

android:lines="3" 
android:scrollHorizontally="false" 

Aus irgendeinem Grund funktioniert dies jedoch nur, wenn ich diese Einstellungen im Code anstelle der Layoutdatei (in onCreate) von vornehme

TextView tv = (TextView)findViewById(R.id.editText);
if (tv != null) {
    tv.setHorizontallyScrolling(false);
    tv.setLines(3);
}

Ich hoffe, das hilft jemandem, da es eine Weile gedauert hat, es herauszufinden. Wenn Sie einen Weg finden, es aus dem Manifest heraus zum Laufen zu bringen, lassen Sie es uns bitte wissen.

HYS
quelle
4
Ich würde auch vorschlagen, es zu versuchen, maxLines()anstatt setLines()zu vermeiden, die Höhe desEditText
Daniel Smith
Ich denke, dass in der Frage nicht klar ist, dass Sie android: imeOptions mit einem Wert wie actionSend setzen sollten. Um diese Antwort zu vervollständigen, musste ich android: singleLine = "true" setzen, auch wenn setMaxLines es irgendwie durch Code überschreibt (wenn Sie dies nicht tun, erhalten Sie keine Eingabetaste mit z. B. "Senden"). Überprüfen Sie die erste Antwort von stackoverflow.com/questions/5014219/… out , um die Aktion <Eingabe> zu erfassen .
DNax
Entschuldigung, die beste Alternative, die ich zum Erfassen der <Eingabe> gefunden habe, ist die Antwort von @earlcasper
DNax
1
Das hat perfekt für mich funktioniert (mit setMaxLines(3)) Vielen Dank!
Laurencevs
1
Funktionierte wie ein Zauber: Fügen Sie einfach android: imeOptions = "actionDone" android: inputType = "text" zu Ihrem XML hinzu und entfernen Sie android: lines = "3" android: scrollHorizontally = "false" aus XML
HannahCarney
24

Arbeitsbeispiel! Erstellen Sie die folgende benutzerdefinierte EditText-Klasse, die diese Funktion unterstützt, und verwenden Sie die Klasse in der XML-Datei. Arbeitscode:

package com.example;

import android.content.Context;
import android.util.AttributeSet;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.widget.EditText;

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;
   }
}

<com.example.ActionEditText
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:imeOptions="actionDone"
       android:inputType="textAutoCorrect|textCapSentences|textMultiLine" />
Anees U.
quelle
Dies funktionierte für mich. Meine Anforderung war es, einen Bearbeitungstext zu erstellen, der mehrzeilig sein und die nächste Schaltfläche auf den Softkeys haben sollte. Also vielen Dank, was ich getan habe war in Text bearbeiten Ich habe 2 Zeilen hinzugefügt android: inputType = "textMultiLine" android: imeOptions = "actionNext" Und in der obigen benutzerdefinierten Klasse habe ich: InputConnection conn = super.onCreateInputConnection (outAttrs); //outAttrs.imeOptions & = ~ EditorInfo.IME_FLAG_NO_ENTER_ACTION; outAttrs.imeOptions & = EditorInfo.IME_ACTION_NEXT; return conn;
Yash
Funktioniert. Getestet auf Andorid 6.0.1.
AmiguelS
9

Um dies in Kotlin zu tun (und optional auch andere Konfigurationen anzuwenden, wie textCapSentencesSie diese Erweiterungsfunktion verwenden können:

// To use this, do NOT set inputType on the EditText in the layout
fun EditText.setMultiLineCapSentencesAndDoneAction() {
    imeOptions = EditorInfo.IME_ACTION_DONE
    setRawInputType(InputType.TYPE_TEXT_FLAG_CAP_SENTENCES or InputType.TYPE_TEXT_FLAG_MULTI_LINE)
}

Verwendung:

myEditText.setMultiLineCapSentencesAndDoneAction()
Ollie C.
quelle
1
Funktioniert ab Juni 2019! Danke :)
Rohan Taneja
Der Schlüssel für mich war, setRawInputTypeanstelle vonsetInputType
Tamoxin
9

Ich denke, das ist der Weg, um dich zu machen. Wenn Sie haben android:inputType="textMultiLine", android:imeOptions="actionDone"wird die Funktionalität der Eingabetaste nicht eindeutig. Denken Sie daran, dass Sie verwenden android:lines="10"und möglicherweise entfernen können android:inputType="textMultiLine", aber es hängt davon ab, was Sie erreichen möchten. Manchmal benötigen Sie nur das android:inputType="textMultiLine"und es gibt keinen Ersatz dafür.

EditText ed=new EditText(this);
ed.setOnKeyListener(new OnKeyListener() {
        @Override
        public boolean onKey(View v, int keyCode, KeyEvent event) {
            if(keyCode == KeyEvent.KEYCODE_ENTER){
                //do your stuff here
            }
            return false;
        }
});
Lukap
quelle
Die Verwendung einer festen Anzahl von Maximalzahlen mit Android: lines = "10" hat bei mir funktioniert und die OK-Taste auf der Tastatur angezeigt. Guter Trick, wenn man weiß, wie viele Zeilen es geben wird, zum Beispiel mit einem kleinen maxLength-Set.
Sunadorer
Ich möchte keyCode # 66 deaktivieren. Ist das möglich? Wie kann ich das machen?
Adil Malik
1
Warum keyCode == 66 statt keyCode == EditorInfo.IME_ACTION_GO?
tse
5

Das scheint für mich perfekt zu funktionieren

int lineNum = 2;
mEditText.setHorizontallyScrolling(false);
mEditText.setLines(3);
Yonez
quelle
4

Wiederverwendbare Kotlin-Lösung

Das Festlegen dieser Werte im Code war das einzige, was für mich funktioniert hat

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

Ich benötige dies häufig, um den Code sauber zu halten:

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

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

Wenn Sie eine optionale benutzerdefinierte Aktion für "Fertig" hinzufügen möchten, versuchen Sie Folgendes:

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()

Müssen Sie die Tastatur im Rückruf einfach steuern? Lesen Sie diesen Beitrag

Fügen Sie dann einen hideKeyboard()Anruf hinzuEditText.multilineDone

Gibolt
quelle
1
☝️Das ist eine großartige Antwort
Michael
3

Kurze Antwort: Nein, ich glaube, es ist vor API Level 11 (3.0) nicht möglich.

Das gleiche Problem tauchte hier auf (in den Kommentaren zur akzeptierten Antwort besprochen):

Android Soft Tastatur Aktionstaste

Aus dem letzten Kommentar:

Wenn Sie sich einige Apps auf meinem Telefon ansehen, scheint es üblich zu sein, dass die mehrzeilige Box zuletzt mit einer sichtbaren Schaltfläche "Fertig" oder "Senden" darunter angezeigt wird (z. B. E-Mail-App).

Martin Stone
quelle
3

Ein einfacher Weg, um diese Situation zu umgehen:

  • Behalten Sie diese Attribute im EditText bei:

    android:inputType="textMultiLine" 
    android:scrollHorizontally="false"
  • Fügen Sie dann diesen Code hinzu, um die Tastatur nur auszublenden, wenn Sie die EINGABETASTE drücken:

    editText.setOnEditorActionListener(new OnEditorActionListener() 
    {
        public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
        if (event.getKeyCode() == KeyEvent.KEYCODE_ENTER) 
        {
            editText.setSelection(0);
            InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
            imm.hideSoftInputFromWindow(editText.getWindowToken(), 0);      
            return true;
         } 
         else 
         {
            return false;
         }
         }
    });
Jean Gonçalves
quelle
2

Wenn es nicht um das Aussehen der Bildschirmtastatur geht, können Sie einfach einen Eingabe-Listener auf die Tastatur setzen und den Status "erledigt" auslösen, wenn der Benutzer eine neue Zeile eingibt.

zwei
quelle
2

Wenn Sie die Eingabeoption textImeMultiline mit den Imeoptionen flagnext und actionnext verwenden, erhalten Sie anstelle der Cariage-Rückgabe eine nächste Schaltfläche

Marcusdev
quelle
2

Während keine der anderen Lösungen jemals für mich funktioniert hat, hat die folgende wunderbar funktioniert und mir Tage und Tage mehr Googeln erspart, natürlich mit ein paar eigenen Wendungen. Leider kann ich mich nicht erinnern, woher ich den Code genau habe, und kann dem Autor daher nicht die Anerkennung geben, die er verdient.

In Ihrem Java-Code:

////////////Code to Hide SoftKeyboard on Enter (DONE) Press///////////////
editText.setRawInputType(InputType.TYPE_CLASS_TEXT|InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD|InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
editText.setImeActionLabel("DONE",EditorInfo.IME_ACTION_DONE);              //Set Return Carriage as "DONE"
editText.setImeOptions(EditorInfo.IME_ACTION_DONE);

editText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
    @Override
    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) 
    {
                if (event == null) {
                    if (actionId == EditorInfo.IME_ACTION_DONE) {
                        // Capture soft enters in a singleLine EditText that is the last EditText
                        // This one is useful for the new list case, when there are no existing ListItems
                        editText.clearFocus();
                        InputMethodManager inputMethodManager = (InputMethodManager)  getActivity().getSystemService(Activity.INPUT_METHOD_SERVICE);
                        inputMethodManager.hideSoftInputFromWindow(getActivity().getCurrentFocus().getWindowToken(), 0);
                    }

                    else if (actionId == EditorInfo.IME_ACTION_NEXT) {
                        // Capture soft enters in other singleLine EditTexts
                    } else if (actionId == EditorInfo.IME_ACTION_GO) {
                    } else {
                        // Let the system handle all other null KeyEvents
                        return false;
                    }
                } 
        else if (actionId == EditorInfo.IME_NULL) {
                    // Capture most soft enters in multi-line EditTexts and all hard enters;
                    // They supply a zero actionId and a valid keyEvent rather than
                    // a non-zero actionId and a null event like the previous cases.
                    if (event.getAction() == KeyEvent.ACTION_DOWN) {
                        // We capture the event when the key is first pressed.
                    } else {
                        // We consume the event when the key is released.
                        return true;
                    }
                } 
        else {
                    // We let the system handle it when the listener is triggered by something that
                    // wasn't an enter.
                    return false;
                }
                return true;
        }
});
Kaushik NP
quelle
1

Ich bin auf 4.x und habe versucht, setHorizontallyScrolling () (mit oder ohne setLine () oder setMaxLines ()) sowie viele verschiedene XML-Konfigurationen aufzurufen, damit die Schaltfläche Fertig angezeigt wird. Keiner von ihnen hat funktioniert. Die Quintessenz ist, dass Android, wenn Ihr EditText mehrzeilig ist, immer den Wagenrücklauf anstelle der Schaltfläche "Fertig" anzeigen möchte, es sei denn, Sie haben einen Hack dazu durchgeführt.

Die Lösung mit der geringsten Komplikation, bei der ich festgestellt habe, dass das Verhalten des Wagenrücklaufs nicht neu zugeordnet werden muss, ist hier: https://stackoverflow.com/a/12570003/3268329 . Diese Lösung macht den unerbittlichen Wunsch von Android zunichte, das Setzen des IME_FLAG_NO_ENTER_ACTION-Flags für mehrzeilige Ansichten zu erzwingen, wodurch die Schaltfläche "Fertig" verschwindet.

Steve B.
quelle
0

Ich hatte auch einige Zeit Probleme, aber ich fand endlich eine Lösung!

Erstellen Sie einfach eine benutzerdefinierte EditText-Klasse als solche:

public class EditTextImeMultiline extends EditText {

    public void init() {
        addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {

            }

            @Override
            public void afterTextChanged(Editable s) {
                for (int i = s.length(); i > 0; i--)
                    if (s.subSequence(i - 1, i).toString().equals("\n"))
                        s.replace(i - 1, i, "");
            }
        });
        setSingleLine();
        setHorizontallyScrolling(false);
        this.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                EditTextImeMultiline.this.setLines(EditTextImeMultiline.this.getLineCount());
            }
        });
    }

    public EditTextImeMultiline(Context context) {
        super(context);
        init();
    }

    public EditTextImeMultiline(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public EditTextImeMultiline(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public EditTextImeMultiline(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init();
    }
}

Diese Klasse entfernt lineBreaks (\ n), umschließt den Text wie textMultiline und ermöglicht es Ihnen, die Eingabetaste durch eine ImeAction zu ersetzen;).

Sie müssen es nur in Ihrem XML anstelle der klassischen EditText-Klasse aufrufen.

Um die Logik hier zu erklären:

  • Legen Sie den EditText als einzelne Zeile fest, um eine ImeAction-Schaltfläche anstelle der Eingabetaste anzeigen zu können.
  • Entfernen Sie den horizontalen Bildlauf, damit der Text am Ende der Ansicht in die nächste Zeile wechselt.
  • Beobachten Sie die Layoutänderungen mit dem onGlobalLayoutListener und setzen Sie den Parameter "line" auf "lineCount" des aktuellen Textes, der im editText enthalten ist. Dies ist es, was seine Höhe erfrischt.
Gabriel Morin
quelle