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.