Modifica testo su più righe con pulsante di azione Fatto


114

È possibile avere un EditTextwidget con android:inputType="textMultiLine"set e android:imeOptions="actionDone"allo stesso tempo?

Vorrei una casella di modifica su più righe, con il pulsante di azione sulla tastiera da fare, non Invio (ritorno a capo), ma non sembra funzionare ..

Grazie in anticipo


Che ne dici di provare un widget composto con EditText multilinea e un pulsante combinati insieme?
Subin Sebastian

Risposte:


195

Uso

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

e in XML:

android:inputType="textMultiLine"

per me il cursore sarebbe ancora mostrato quando la tastiera si è abbassata, dovevo aggiungere textField.setCursorVisible(false);all'interno di unonEditorActionListener
Fonix

Funziona su 4.2.2 e 7.1.1. Grazie.
tehcpu

1
Funziona molto bene ... ho faticato a trovarlo. Questa risposta deve essere contrassegnata come risposta migliore
MFAL

7
perché funziona invece di impostare tutto in xml?
Andrew Steinmetz

1
Abit ha lottato per trovare queste informazioni. Funziona ancora come un incantesimo!
Costin

51

Dalla documentazione di Android: " " textMultiLine "Tastiera di testo normale che consente agli utenti di inserire lunghe stringhe di testo che includono interruzioni di riga (ritorni a capo ) . 'Pertanto l'attributo textMultiLine non è appropriato se vuoi avere il pulsante' Done 'sulla tastiera.

Un modo semplice per ottenere un campo di input su più righe (in questo caso 3 righe) con il pulsante fatto è usare EditText con

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

Tuttavia, per qualche motivo questo funziona solo per me se eseguo queste impostazioni nel codice anziché nel file di layout (in onCreate) da

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

Spero che questo aiuti qualcuno, poiché ci è voluto un po 'di tempo per capirlo. Se trovi un modo per farlo funzionare dal manifest, faccelo sapere.


4
Suggerirei anche di provare maxLines()invece di, setLines()se vuoi evitare di cambiare l'altezza diEditText
Daniel Smith

Penso che nella domanda non sia chiarito che dovresti impostare android: imeOptions con un valore come actionSend. Completando questa risposta, ho dovuto impostare android: singleLine = "true" anche se il tipo setMaxLines lo sovrascrive con il codice (non farlo non ti darà una chiave di invio con es. "Invia"). Per acquisire l'azione <Enter>, controlla la prima risposta da stackoverflow.com/questions/5014219/… out.
DNax

Siamo spiacenti, il migliore che ho trovato un'alternativa di catturare <ENTER> è @earlcasper risposta qui stackoverflow.com/questions/1489852/...~~V~~singular~~3rd
DNax

1
Questo ha funzionato perfettamente per me (usando setMaxLines(3)) Grazie mille!
laurencevs

1
Ha funzionato a meraviglia: aggiungi semplicemente android: imeOptions = "actionDone" android: inputType = "text" al tuo XML e rimuovi android: lines = "3" android: scrollHorizontally = "false" da XML
HannahCarney

24

Esempio di lavoro! Crea la seguente classe EditText personalizzata che supporta questa funzione e usa la classe nel file xml. Codice di lavoro:

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" />

Questo ha funzionato per me, la mia esigenza era di creare un testo di modifica che dovrebbe essere su più righe e dovrebbe avere il pulsante successivo sui tasti funzione ............... quindi grazie mille per quello che ho fatto era in modifica testo ho aggiunto 2 linee android: inputType = "textMultiLine" android: imeOptions = "actionNext" E nella classe personalizzata sopra ho fatto: InputConnection conn = super.onCreateInputConnection (outAttrs); //outAttrs.imeOptions & = ~ EditorInfo.IME_FLAG_NO_ENTER_ACTION; outAttrs.imeOptions & = EditorInfo.IME_ACTION_NEXT; return conn;
yash

Lavori. Testato su Andorid 6.0.1.
AmiguelS

9

Per fare ciò in Kotlin (e anche applicare facoltativamente altre configurazioni come textCapSentencespuoi usare questa funzione di estensione:

// 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)
}

Uso:

myEditText.setMultiLineCapSentencesAndDoneAction()

1
Funziona da giugno 2019! Grazie :)
Rohan Taneja

La chiave per me era usare al setRawInputTypeposto disetInputType
Tamoxin il

9

Penso che questo sia il modo per farti le cose. Avere android:inputType="textMultiLine", android:imeOptions="actionDone"rende ambigue le funzionalità chiave di immissione. Tieni presente che puoi usare android:lines="10"e forse rimuovere android:inputType="textMultiLine", ma dipende da cosa vuoi ottenere a volte hai solo bisogno di android:inputType="textMultiLine"e non c'è sostituzione per esso.

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

L'utilizzo di una quantità fissa di numeri massimi con android: lines = "10" ha funzionato per me, ottenendo il pulsante ok sulla tastiera. Un buon trucco se si sa quante righe ci saranno, ad esempio con un piccolo maxLength impostato.
sunadorer

Voglio disabilitare il KeyCode # 66 è possibile? Come lo posso fare?
Adil Malik

1
perché keyCode == 66 invece keyCode == EditorInfo.IME_ACTION_GO?
tse

5

Questo sembra funzionare perfettamente per me

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

4

Soluzione Kotlin riutilizzabile

L'impostazione di questi valori nel codice è stata l'unica cosa che ha funzionato per me

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

Ne ho bisogno frequentemente, quindi l'ho fatto per mantenere pulito il codice:

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)

Se desideri aggiungere un'azione personalizzata facoltativa su "Fine", prova questo:

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

Hai bisogno di controllare facilmente la tastiera durante la richiamata? Leggi questo post

Quindi aggiungi la hideKeyboard()chiamataEditText.multilineDone


1
☝️Questa è un'ottima risposta
Michael

3

Risposta breve: No, credo che non sia possibile prima del livello API 11 (3.0).

Lo stesso problema è emerso qui (discusso nei commenti alla risposta accettata):

Pulsante di azione della tastiera morbida Android

Dal commento finale:

Guardando alcune app sul mio telefono, sembra comune avere la casella multilinea per ultima, con un pulsante visibile "Fine" o "Invia" sotto di essa (ad es. App Email).


3

Un modo semplice per aggirare questa situazione:

  • mantieni questi attributi su EditText:

    android:inputType="textMultiLine" 
    android:scrollHorizontally="false"
  • quindi aggiungi questo codice per nascondere la tastiera solo quando viene premuto INVIO:

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

2

Se non si tratta dell'aspetto della tastiera su schermo, potresti semplicemente mettere un listener di input sulla tastiera e attivare lo stato "fatto" se l'utente inserisce una nuova riga.


2

se si utilizza l'opzione di input textImeMultiline con imeoptions flagnext e actionnext si ottiene un pulsante successivo al posto del ritorno del carrello


2

Sebbene nessuna delle altre soluzioni abbia mai funzionato per me, quanto segue ha funzionato magnificamente e mi ha salvato giorni e giorni di più ricerche su Google, con alcuni miei colpi di scena ovviamente. Sfortunatamente non ricordo da dove ho preso esattamente il codice e quindi non posso dare all'autore il credito che merita.

Nel tuo codice Java:

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




1

Sono su 4.x e ho provato a chiamare setHorizontallyScrolling () (con o senza setLine () o setMaxLines ()), oltre a molte diverse configurazioni XML per visualizzare il pulsante Fine. Nessuno di loro ha funzionato. La linea di fondo è che se il tuo EditText è multilinea, Android vorrà sempre mostrare il ritorno a capo invece del pulsante "Fatto", a meno che tu non inserisca qualche trucco intorno a questo.

La soluzione meno complicata che ho trovato che non comporta la rimappatura del comportamento del ritorno a capo è qui: https://stackoverflow.com/a/12570003/3268329 . Questa soluzione annullerà il desiderio incessante di Android di forzare l'impostazione del flag IME_FLAG_NO_ENTER_ACTION per le visualizzazioni multilinea, il che fa scomparire il pulsante Fine.


0

Anche io ho faticato per un po 'di tempo, ma finalmente ho trovato una soluzione!

Basta creare una classe EditText personalizzata come tale:

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

Questa classe rimuove lineBreaks (\ n), avvolge il testo come farebbe textMultiline, E ti permette di sostituire il pulsante Invio con una ImeAction;).

Devi solo chiamarlo nel tuo XML invece della classica classe EditText.

Per spiegare la logica qui:

  • Imposta EditText come singleLine per poter mostrare un pulsante ImeAction invece di Enter.
  • Rimuovere lo scorrimento orizzontale per far passare il testo alla riga successiva quando si raggiunge la fine della visualizzazione.
  • Guarda le modifiche al layout con onGlobalLayoutListener e imposta il suo parametro "line" sul "lineCount" del testo corrente contenuto in editText. Questo è ciò che rinfresca la sua altezza.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.