EditText maxLines funktioniert nicht - Benutzer kann immer noch mehr Zeilen als festgelegt eingeben

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

Der Benutzer kann mehr als 5 Zeilen eingeben, indem er die Eingabetaste / die nächste Zeilentaste drückt. Wie kann ich Benutzereingaben mit EditText auf eine feste Anzahl von Zeilen beschränken?

Indrek Kõue
quelle
siehe diesen Beitrag: stackoverflow.com/questions/14672234/…
ali safaei

Antworten:

84

Das Attribut maxLinesentspricht der maximalen Höhe von EditText, es steuert die äußeren Grenzen und nicht die inneren Textzeilen.

Cedekasme
quelle
Das habe ich auch gedacht ... Gibt es eine Möglichkeit, die eingegebenen Zeilen einzuschränken, oder muss ich sie programmgesteuert im Backend-Code verwenden?
Indrek Kõue
Es gibt keine einfache Möglichkeit, die eingegebenen Zeilen wie gewünscht einzuschränken. Sie müssen dies manuell in Ihrem Code tun.
Cedekasme
3
Ich denke für einen Entwickler impliziert "maxLines" die maximale Anzahl von Zeilen, die mit einem editText möglich sein sollten. Wenn ich nur eine bestimmte Höhe wollte, würde ich "Linien" verwenden. : - /
Jemand irgendwo
241
<EditText
    android:id="@+id/edit_text"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:inputType="text"
    android:maxLines="1" 
/>

Sie müssen nur sicherstellen, dass Sie das Attribut "inputType" festgelegt haben. Ohne diese Zeile geht es nicht.

android:inputType="text"
Noel Chew
quelle
3
@Neol Chew Du hast recht! Ich habe nach dem Einstellen inputTypeauf gearbeitet text. Danke, dass du mir Zeit gespart
hast
6
@byJeevan, ich dachte immer, inputType hat den Standardwert "text". Ich glaube, ich habe mich geirrt.
Noel Chew
2
Sehr seltsam, dass Text nicht der Standardwert für inputType ist. Gute Antwort
Muhammed Refaat
9
es funktioniert nur für maxLines von 1, aber Sie können keine neue Zeile hinzufügen
Daniel Raouf
68

Dies löst nicht das allgemeine Problem der Beschränkung auf n Zeilen. Wenn Sie Ihren EditText auf nur eine Textzeile beschränken möchten, kann dies sehr einfach sein.
Sie können dies in der XML-Datei festlegen.

android:singleLine="true"

oder programmatisch

editText.setSingleLine(true);
Jesse Black
quelle
8
aber was ist, wenn Sie auf 2 Zeilen beschränken möchten? oder 3? Dafür müssen Sie einen benutzerdefinierten Zeilenbegrenzer bauen ...
Indrek Kõue
4
Das ist mir bewusst. "Dies löst nicht das allgemeine Problem der Beschränkung auf n Zeilen". Am Ende habe ich die Frage hier durchgelesen, während ich versucht habe, mich auf eine Zeile zu beschränken, und eine einfachere Lösung gefunden. Ich dachte, andere könnten hier landen und versuchen, ihren EditText auf eine Zeile zu beschränken und den "benutzerdefinierten Zeilenbegrenzer" zu implementieren. Meine Antwort ist hier für andere SO-Benutzer, die diese Frage aus demselben Grund wie ich suchen.
Jesse Black
@ IndrekKõue das sollte nicht zu schwer sein.
Don Larynx
10
singleLine ist veraltet
Ali
1
editText's Attribut singleLine = "true" ist veraltet und es wird abstürzen bei Geräten, die bei Android größer als 7.0 verwendet werden
TranHieu
24

@ Cedekasem Sie haben Recht, es gibt keinen eingebauten "Zeilenbegrenzer". Aber ich habe selbst eines gebaut. Wenn also jemand interessiert ist, ist der Code unten. Prost.

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;
        }
});
Indrek Kõue
quelle
Dies hat einen nicht intuitiven Nebeneffekt für den Benutzer. Wenn Sie beispielsweise 7 Zeilen in Ihrem EditText haben und dann in der Mitte die Eingabetaste drücken, können Sie sich von der letzten Zeile Ihres Textes verabschieden.
miguel.martin
funktioniert nicht, wenn Sie mehr als maxlines Text einfügen. Besser wäre es also, addTextChangedListener zu verwenden.
Kuldeep Sakhiya
13

Ich habe so etwas gemacht, wie ihr gesucht habt. Hier ist meine LimitedEditTextKlasse.

Eigenschaften:

  • Sie können die Zeilenanzahl in Ihrer LimitedEditText-Komponente begrenzen
  • Sie können die Anzahl der Zeichen in Ihrer LimitedEditText-Komponente begrenzen
  • Wenn Sie die Anzahl der Zeichen oder Zeilen irgendwo in der Mitte des Textes überschreiten,
    bringt Sie der Cursor nicht zum Ende - er bleibt dort, wo Sie waren.

Ich schalte den Listener aus, weil jeder Aufruf der setText()Methode diese 3 Rückrufmethoden rekursiv aufrufen würde, falls der Benutzer das Zeichen- oder Zeilenlimit überschreitet.

Code:

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

}
bpawlowski
quelle
2
Diese Lösung ist so einfach und elegant! Danke
GuilhE
Ich benutze beforeCursorPosition = getSelectionStart();im afterTextChangedRückruf. Es funktioniert besser , weil , wenn die Eingabe enach der Eingabe abcd, die EditText ‚denken‘ können Sie ersetzen abcdmit abcde, weil der Eingabemethode Grund.
Hanswim
11

Ich habe dafür eine einfachere Lösung gefunden: 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);
        }
    });

Sie können den Wert 3 in txtSpecialRequests.getLineCount() > 3an Ihre Bedürfnisse anpassen.

Oscar Yuandinata
quelle
3
Vielen Dank, endlich nach mehreren falschen Lösungen gearbeitet. Dies sollte die akzeptierte Antwort sein.
eyadMhanna
Ich verstehe, dass "txtSpecialRequests" Ihr EditText-Container ist, aber wo setzen Sie die Variablen lastSpecialRequestsCursorPosition und specialRequests?
Drearypanoramic
außerhalb dieser Methode natürlich :) init lastSpecialRequestsCursorPosition = 0 und specialRequests = ""
Oscar Yuandinata
Tolle Lösung!
Marcus
5

Hier ist ein InputFilter, der die zulässigen Zeilen in EditText begrenzt:

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

So fügen Sie es EditText hinzu:

editText.setFilters(new InputFilter[]{new MaxLinesInputFilter(2)});
Peceps
quelle
Gute Lösung, aber es geht um das Problem des Textumbruchs (nicht eingeben)
Peter File
4

Folgendes habe ich in meinem Projekt verwendet:

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

Und es hat in allen Szenarien funktioniert

Pirat
quelle
1
Welchen Kontext benötigt der TextWatcher? Der KeyListener war alles was ich brauchte.
AlanKley
@AlanKley: Wir müssen vor und nach dem Text Ereignisse ändern, um die Anzahl der Zeilen von editText zu berechnen. Als ob wir weiterhin Text eingeben und nicht die Taste "Neue Zeile" drücken, wird onKey nicht ausgelöst und der Cursor bewegt sich automatisch zur nächsten Zeile. Um diese Art von Zeilen zu verfolgen, benötigen wir textWatcher. Ich hoffe, ich kann Sie verständlich machen.
Pirat
Aha. Vielen Dank für diese Klarstellung.
AlanKley
@AlanKley Wenn du denkst, dass meine Antwort nützlich ist, stimme bitte dafür.
Pirat
public void afterTextChanged (Editable arg0) {int lineCount = editText.getLineCount (); if (lineCount> numberOfLines) {editText.setText (text); }} wird eine
StackOverflowException auslösen
4

setze editText android:inputType="text"

Vimal Prabhu
quelle
3

Einfachste Lösung:

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());
}
Landonmutch
quelle
3
android:inputType="text" (or something different to "none")
android:maxLines="1"  (and this line)
Adrián Prieto
quelle
2

Dies ist ein Ansatz. Könnte jemandem helfen.

android:lines="1"
android:maxLines="1"
android:inputType="text
Mohammed Nathar
quelle
1

Eine andere Möglichkeit, Ihre EditTextZeile zu beschränken , ist die folgende:

editText2.setTransformationMethod(new SingleLineTransformationMethod());

Beachten Sie, dass nach Anwendung dieser Transformationsmethode die Eingabetaste beim Drücken Leerzeichen erzeugt. Das befriedigt immer noch die Frage von TS.

giorgos.nl
quelle
Schöne Art, neue Linie zu verstecken! Im Wert wird es jedoch immer noch ein 'neue Zeile' Zeichen geben !!
Gregory Stein
1

Sie können Ihren Text entsprechend Ihrer Zeilenanzahl einschränken, ich sage etwa 37 Alphabete in einer Zeile

<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"/>
nafees ahmed
quelle
0

getLineCount () ist eine Option; Wenn Sie dort Werte ungleich Null wünschen, stellen Sie sicher, dass Ihre Ansicht gemessen wird. Bei Softtastaturen funktioniert onKeyListener nicht, daher müssen Sie addTextChangedListener () hinzufügen, um Textänderungen während der Eingabe zu verfolgen. Sobald Sie genügend Zeilen in den Rückrufen erhalten, tun Sie, was Sie möchten, um es einzuschränken: Löschen Sie Zeichen mit getText (), setText () oder etwas Besonderem. Sie können die Anzahl der Zeichen sogar mithilfe eines Filters begrenzen.

Eine weitere Option ist die Überwachung der Textgröße mit getLineBounds (). Dies wirkt sich auf die Schwerkraft / das Paddign des Textes aus. Seien Sie also vorsichtig.

Vlad
quelle
0

Um die Anzahl der Zeichen zu begrenzen, können Sie einfach die Eigenschaft maxLength von EditText verwenden, da der Benutzer keine weiteren Zeichen eingeben kann.

Pirat
quelle
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" />
Atiar Talukdar
quelle
0

Eine andere Idee: Jedes Mal nach der Eingabe wird neuer Text in einem String lastText gespeichert, nur wenn die Anzahl der Zeilen MAX_LINES nicht überschreitet. In diesem Fall setzen wir den Text von EditText auf den zuletzt hinzugefügten Text (damit die Änderungen gelöscht werden) und benachrichtigen den Benutzer, ihn kurz zu halten.

 // 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();
            }
        }
    });
Amir Golan
quelle
0

Dies ist eine Erweiterung der Antwort von Indrek Kõue auf 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)
                    }
                }
            })
Константин Казаченко
quelle
-4

Versuchen Sie, die folgende Kombination von Attributen des EditText in der XML-Datei zu verwenden:

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

ihayet
quelle
2
Nur ein Kopf hoch. singleLine ist veraltet. maxLines wurde anstelle von singleLine eingeführt.
Sandeep R
@ SandepR Sie sind falsch, android:inputTypeersetzt die Verwendung vonandroid:singleLine
Pierre