EditText maxLines non funziona: l'utente può comunque inserire più righe di quelle impostate


126
<EditText 
    android:id="@+id/editText2" 
    android:layout_height="wrap_content" 
    android:layout_width="fill_parent" 
    android:maxLines="5" 
    android:lines="5">
</EditText>

L'utente può inserire più di 5 righe, premendo il tasto Invio / riga successiva. Come posso limitare l'input dell'utente a un numero fisso di righe con EditText?


Risposte:


84

L'attributo maxLinescorrisponde all'altezza massima di EditText, controlla i confini esterni e non le righe di testo interne.


Questo è quello che ho pensato anche ... C'è un modo per limitare le linee immesse o devo farlo sul codice di backend a livello di codice?
Indrek Kõue,

Non esiste un modo semplice per limitare le linee immesse come desiderato. Dovrai farlo manualmente nel tuo codice.
Cedekasme,

3
Penso che uno sviluppatore "maxLines" implichi il numero massimo di righe che dovrebbe essere possibile con un editText. Se volessi solo un'altezza specifica, userei le "linee". : - /
Someone Somewhere

241
<EditText
    android:id="@+id/edit_text"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:inputType="text"
    android:maxLines="1" 
/>

Devi solo assicurarti di avere l'attributo "inputType" impostato. Non funziona senza questa linea.

android:inputType="text"

3
@Neol Chew Hai ragione! Ho lavorato dopo aver impostato inputTypea text. Grazie per
avermi

6
@byJeevan, ho sempre pensato che inputType abbia un valore predefinito di "testo". Immagino di aver sbagliato.
Noel Mastica il

2
Molto strano che Text non sia il valore predefinito impostato per inputType, Great Answer però
Muhammed Refaat,

9
funziona solo per maxLines di 1 ma non è possibile aggiungere una nuova riga
Daniel Raouf,

68

Questo non risolve il problema generale della limitazione a n righe. Se vuoi limitare il tuo EditText per prendere solo 1 riga di testo, questo può essere molto semplice.
Puoi impostarlo nel file xml.

android:singleLine="true"

o programmaticamente

editText.setSingleLine(true);

8
ma cosa succede se si desidera limitare a 2 righe? o 3? Per questo devi costruire un limitatore di riga personalizzato ...
Indrek Kõue,

4
Ne sono consapevole. "Questo non risolve il problema generale della limitazione a n righe". Ho finito per leggere la domanda qui mentre cercavo di limitarmi a 1 riga e ho trovato una soluzione più semplice. Immaginavo che altri potessero finire qui cercando di limitare il loro EditText a 1 riga e implementare il "limitatore di righe personalizzato". La mia risposta è qui per altri utenti SO che finiscono per cercare questa domanda per lo stesso motivo che ho fatto.
Jesse Black,

@ IndrekKõue che non dovrebbe essere troppo difficile.
Don Larynx,

10
singleLine è obsoleto
Ali

1
L'attributo di editText singleLine = "true" è obsoleto e si bloccherà quando i dispositivi utilizzano Android più grande di 7.0
TranHieu

24

@Cedekasem hai ragione, non esiste un "limitatore di riga" incorporato. Ma me ne sono fatto uno da solo, quindi se qualcuno è interessato il codice è sotto. Saluti.

et.setOnKeyListener(new View.OnKeyListener() {

        @Override
        public boolean onKey(View v, int keyCode, KeyEvent event) {

            // if enter is pressed start calculating
            if (keyCode == KeyEvent.KEYCODE_ENTER
                    && event.getAction() == KeyEvent.ACTION_UP) {

                // get EditText text
                String text = ((EditText) v).getText().toString();

                // find how many rows it cointains
                int editTextRowCount = text.split("\\n").length;

                // user has input more than limited - lets do something
                // about that
                if (editTextRowCount >= 7) {

                    // find the last break
                    int lastBreakIndex = text.lastIndexOf("\n");

                    // compose new text
                    String newText = text.substring(0, lastBreakIndex);

                    // add new text - delete old one and append new one
                    // (append because I want the cursor to be at the end)
                    ((EditText) v).setText("");
                    ((EditText) v).append(newText);

                }
            }

            return false;
        }
});

Questo ha un effetto collaterale non intuitivo per l'utente. ad es. se ci sono 7 righe nel tuo EditText e premi Invio al centro di esso, allora puoi dire ciao all'ultima riga del tuo testo.
miguel.martin,

non funzionerà se si incolla più di maxline di testo. Quindi sarebbe meglio usare addTextChangedListener.
Kuldeep Sakhiya,

13

Ho fatto qualcosa che voi ragazzi stavate cercando. Ecco la mia LimitedEditTextlezione.

Caratteristiche:

  • puoi limitare il conteggio delle righe nel componente LimitedEditText
  • puoi limitare il conteggio dei caratteri nel componente LimitedEditText
  • se superi il limite di caratteri o linee da qualche parte nel mezzo del testo, il cursore
    non ti porterà alla fine - rimarrà dove sei stato.

Sto disattivando l'ascoltatore, perché ogni chiamata di setText() metodo chiamerebbe ricorsivamente questi 3 metodi di callback nel caso in cui l'utente superi il limite di caratteri o linee.

Codice:

import android.content.Context;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.EditText;
import android.widget.Toast;

/**
* EditText subclass created to enforce limit of the lines number in editable
* text field
*/
public class LimitedEditText extends EditText {

/**
 * Max lines to be present in editable text field
 */
private int maxLines = 1;

/**
 * Max characters to be present in editable text field
 */
private int maxCharacters = 50;

/**
 * application context;
 */
private Context context;

public int getMaxCharacters() {
    return maxCharacters;
}

public void setMaxCharacters(int maxCharacters) {
    this.maxCharacters = maxCharacters;
}

@Override
public int getMaxLines() {
    return maxLines;
}

@Override
public void setMaxLines(int maxLines) {
    this.maxLines = maxLines;
}

public LimitedEditText(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    this.context = context;
}

public LimitedEditText(Context context, AttributeSet attrs) {
    super(context, attrs);
    this.context = context;
}

public LimitedEditText(Context context) {
    super(context);
    this.context = context;
}

@Override
protected void onFinishInflate() {
    super.onFinishInflate();

    TextWatcher watcher = new TextWatcher() {

        private String text;
        private int beforeCursorPosition = 0;

        @Override
        public void onTextChanged(CharSequence s, int start, int before,
                int count) {                
            //TODO sth
        }

        @Override
        public void beforeTextChanged(CharSequence s, int start, int count,
                int after) {
            text = s.toString();
            beforeCursorPosition = start;
        }

        @Override
        public void afterTextChanged(Editable s) {

            /* turning off listener */
            removeTextChangedListener(this);

            /* handling lines limit exceed */
            if (LimitedEditText.this.getLineCount() > maxLines) {
                LimitedEditText.this.setText(text);
                LimitedEditText.this.setSelection(beforeCursorPosition);
            }

            /* handling character limit exceed */
            if (s.toString().length() > maxCharacters) {
                LimitedEditText.this.setText(text);
                LimitedEditText.this.setSelection(beforeCursorPosition);
                Toast.makeText(context, "text too long", Toast.LENGTH_SHORT)
                        .show();
            }

            /* turning on listener */
            addTextChangedListener(this);

        }
    };

    this.addTextChangedListener(watcher);
}

}

2
Questa soluzione è così semplice ed elegante! Grazie
GuilhE,

Uso beforeCursorPosition = getSelectionStart();nel afterTextChangedcallback. Funziona meglio perché quando digitazione edopo digitazione abcd, l'EditText può 'pensare' si sostituisce abcdcon abcde, a causa del metodo di ragione di input.
Hanswim,

11

Ho reso la soluzione più semplice per questo: D

// set listeners
    txtSpecialRequests.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            lastSpecialRequestsCursorPosition = txtSpecialRequests.getSelectionStart();
        }

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

        }

        @Override
        public void afterTextChanged(Editable s) {
            txtSpecialRequests.removeTextChangedListener(this);

            if (txtSpecialRequests.getLineCount() > 3) {
                txtSpecialRequests.setText(specialRequests);
                txtSpecialRequests.setSelection(lastSpecialRequestsCursorPosition);
            }
            else
                specialRequests = txtSpecialRequests.getText().toString();

            txtSpecialRequests.addTextChangedListener(this);
        }
    });

È possibile modificare il valore di 3 in base txtSpecialRequests.getLineCount() > 3alle proprie esigenze.


3
Grazie mille, finalmente lavorato dopo molteplici soluzioni sbagliate. Questa dovrebbe essere la risposta accettata.
eyadMhanna,

Ho capito che "txtSpecialRequests" è il tuo contenitore EditText, ma dove imposti le variabili lastSpecialRequestsCursorPosition e specialRequests?
Drearypanoramic

al di fuori di questo metodo ovviamente :) init lastSpecialRequestsCursorPosition = 0 e specialRequests = ""
Oscar Yuandinata,

Ottima soluzione!
Marcus,

5

Ecco un InputFilter che limita le righe consentite in EditText:

/**
 * Filter for controlling maximum new lines in EditText.
 */
public class MaxLinesInputFilter implements InputFilter {

  private final int mMax;

  public MaxLinesInputFilter(int max) {
    mMax = max;
  }

  public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
    int newLinesToBeAdded = countOccurrences(source.toString(), '\n');
    int newLinesBefore = countOccurrences(dest.toString(), '\n');
    if (newLinesBefore >= mMax - 1 && newLinesToBeAdded > 0) {
      // filter
      return "";
    }

    // do nothing
    return null;
  }

  /**
   * @return the maximum lines enforced by this input filter
   */
  public int getMax() {
    return mMax;
  }

  /**
   * Counts the number occurrences of the given char.
   *
   * @param string the string
   * @param charAppearance the char
   * @return number of occurrences of the char
   */
  public static int countOccurrences(String string, char charAppearance) {
    int count = 0;
    for (int i = 0; i < string.length(); i++) {
      if (string.charAt(i) == charAppearance) {
        count++;
      }
    }
    return count;
  }
}

Per aggiungerlo a EditText:

editText.setFilters(new InputFilter[]{new MaxLinesInputFilter(2)});

Buona soluzione, tuttavia affronta il problema del ritorno a capo del testo (non inserire)
Peter File,

4

Questo è quello che ho usato nel mio progetto:

editText.addTextChangedListener(new TextWatcher() {
    private String text;

public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {    
}

public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
    text = arg0.toString();
    }

public void afterTextChanged(Editable arg0) {
    int lineCount = editText.getLineCount();
    if(lineCount > numberOfLines){
    editText.setText(text);
    }
}
});

editText.setOnKeyListener(new View.OnKeyListener() {

public boolean onKey(View v, int keyCode, KeyEvent event) {

// if enter is pressed start calculating
    if (keyCode == KeyEvent.KEYCODE_ENTER && event.getAction() == KeyEvent.ACTION_DOWN){    
    int editTextLineCount = ((EditText)v).getLineCount();
    if (editTextLineCount >= numberOfLines)
        return true;
}

return false;
}
});

E ha funzionato in tutti gli scenari


1
Quale contesto è necessario per TextWatcher? KeyListener era tutto ciò di cui avevo bisogno.
AlanKley,

@AlanKley: abbiamo bisogno di eventi di testo prima e dopo il cambio per calcolare il numero di righe di editText. Come se continuiamo a inserire il testo e non premiamo il tasto "nuova riga", il tasto on non si attiva e il cursore si sposta automaticamente sulla riga successiva. Quindi per tenere traccia di questo tipo di linee abbiamo bisogno di textWatcher. Spero di essere in grado di farti capire.
Pirata

Vedo. Grazie per questo chiarimento.
AlanKley,

@AlanKley Se ritieni che la mia risposta sia utile, vota per favore.
Pirata

public void afterTextChanged (Editable arg0) {int lineCount = editText.getLineCount (); if (lineCount> numberOfLines) {editText.setText (testo); }} genererà una StackOverflowException ...
desgraci il


3

La soluzione più semplice:

android:maxLines="3"

...

 @Override
public void afterTextChanged(Editable editable) {
    // limit to 3 lines
    if (editText.getLayout().getLineCount() > 3)
        editText.getText().delete(editText.getText().length() - 1, editText.getText().length());
}

3
android:inputType="text" (or something different to "none")
android:maxLines="1"  (and this line)

2

questo è un approccio. Potrebbe aiutare qualcuno.

android:lines="1"
android:maxLines="1"
android:inputType="text

1

Un altro modo per limitare EditTexta una riga è il seguente:

editText2.setTransformationMethod(new SingleLineTransformationMethod());

Si noti che dopo aver applicato questo metodo di trasformazione, il tasto Invio crea spazi quando viene premuto. Ciò soddisfa ancora la domanda di TS.


Bel modo di nascondere una nuova linea! Nel valore, tuttavia, ci sarà ancora un carattere "nuova riga" !!
Gregory Stein,

1

Puoi limitare il tuo testo in base al tuo numero di righe, dico circa 37 alfabeti in una riga

<EditText
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:lines="4"
    android:maxLines="4"
    android:minLines="4"
    android:maxLength="150"
    android:gravity="start"
    android:background="#efeef5"
    android:layout_marginTop="@dimen/pad_10dp"/>

0

getLineCount () è un'opzione; se desideri valori diversi da zero, assicurati che la tua vista sia misurata. Per la tastiera software onKeyListener non funzionerà, quindi devi aggiungere addTextChangedListener () che terrà traccia delle modifiche al testo durante la digitazione. Non appena ci sono abbastanza linee all'interno delle sue callback, fai quello che vuoi per limitarlo: elimina i caratteri con getText (), setText () o qualcosa di più elegante. Puoi anche limitare il numero di caratteri usando un filtro.

Un'altra opzione è quella di monitorare le dimensioni del testo con getLineBounds (). Questo interagirà con la gravità / paddign del testo, quindi fai attenzione.


0

Per il numero limite di caratteri possiamo semplicemente usare la proprietà maxLength di EditText in quanto non consentirà all'utente di inserire più caratteri.


0
        <EditText
            android:id="@+id/usrusr"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:gravity="center"
            android:lines="1"
            android:maxLines="1"
            android:inputType="text"
            android:hint="@string/inventory_no" />

0

Un'altra idea: ogni volta che si digita, il nuovo testo verrebbe salvato in un String lastText, solo se il numero di righe non supera MAX_LINES. In tal caso, imposteremo il testo di EditText sull'ultimo testo aggiunto (in modo che le modifiche vengano eliminate) e avviseremo l'utente di mantenerlo breve.

 // Set listener to wishDescriptionEditText in order to limit line number
    editText.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) {
            // If line account is higher than MAX_LINES, set text to lastText
            // and notify user (by Toast)
            if (editText.getLineCount() > MAX_LINES) {
                editText.setText(lastText);
                Toast.makeText(getContext(), "Please keep it short", Toast.LENGTH_LONG).show();
            } else {
                lastText = editText.getText().toString();
            }
        }
    });

0

Questa è un'estensione della risposta di Indrek Kõue a Kotlin

                input_name.addTextChangedListener(object : TextWatcher {
                override fun afterTextChanged(s: Editable?) {}

                override fun beforeTextChanged(
                    s: CharSequence?,
                    start: Int,
                    count: Int,
                    after: Int
                ) {
                }

                @SuppressLint("SetTextI18n")
                override fun onTextChanged(
                    s: CharSequence?,
                    start: Int,
                    before: Int,
                    count: Int
                ) {
                    val text = (input_name as EditText).text.toString()
                    val editTextRowCount = input_name.lineCount
                    if (editTextRowCount > 15) {
                        val newText = text.substring(0, text.length - 1)
                        input_name.setText("")
                        input_name.append(newText)
                    }
                }
            })

-4

Prova a utilizzare la seguente combinazione di attributi di EditText all'interno del file xml:

android:singleLine="true"
android:maxLength="22"


2
Solo un avviso. singleLine è obsoleto. maxLines è stato introdotto al posto di singleLine.
Sandeep R

@SandeepR Ti sbagli, android:inputTypesostituisce l'uso diandroid:singleLine
Pierre
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.