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?


Antworten:


84

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


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"

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

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

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

}

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.


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

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


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


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

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

2

Dies ist ein Ansatz. Könnte jemandem helfen.

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

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.


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

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.


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.


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

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

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

-4

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

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


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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.