EditText maxLines tidak berfungsi - pengguna masih dapat memasukkan lebih banyak baris daripada yang ditetapkan


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

Pengguna dapat memasukkan lebih dari 5 baris, dengan menekan tombol enter / baris berikutnya. Bagaimana saya bisa membatasi input pengguna ke jumlah baris tetap dengan EditText?


Jawaban:


84

Atribut maxLinessesuai dengan ketinggian maksimum EditText, itu mengontrol batas luar dan bukan garis teks dalam.


Itu yang saya pikir juga ... Apakah ada cara untuk membatasi baris yang dimasukkan atau apakah saya harus pada kode backend secara terprogram?
Indrek Kõue

Tidak ada cara sederhana untuk membatasi jalur yang dimasukkan seperti yang Anda inginkan. Anda harus melakukannya secara manual dalam kode Anda.
Cedekasme

3
Saya pikir untuk seorang pengembang "maxLines" menyiratkan jumlah maksimum garis yang harus dimungkinkan dengan editText. Jika saya hanya ingin ketinggian tertentu saya akan menggunakan "garis". : - /
Seseorang di suatu tempat

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

Anda hanya perlu memastikan bahwa Anda memiliki set atribut "inputType". Itu tidak bekerja tanpa garis ini.

android:inputType="text"

3
@Neol Chew Kamu benar! Saya bekerja setelah pengaturan inputTypeke text. Terima kasih telah menghemat waktu saya :-)
byJeevan

6
@byJeevan, saya selalu berpikir inputType memiliki nilai default "teks". Kira saya salah.
Noel Chew

2
Sangat aneh bahwa Teks bukan nilai default yang ditetapkan untuk inputType, Jawaban Hebat sekalipun
Muhammed Refaat

9
ini hanya berfungsi untuk maxLines 1 tetapi Anda tidak dapat menambahkan baris baru
Daniel Raouf

68

Ini tidak memecahkan masalah umum membatasi n baris. Jika Anda ingin membatasi EditText Anda hanya dengan 1 baris teks, ini bisa sangat mudah.
Anda dapat mengatur ini di file xml.

android:singleLine="true"

atau secara terprogram

editText.setSingleLine(true);

8
tetapi bagaimana jika Anda ingin membatasi hingga 2 baris? atau 3? Untuk itu, Anda harus membuat pembatas baris khusus ...
Indrek Kõue

4
Saya sadar akan hal itu. + Msgstr "Ini tidak menyelesaikan masalah umum dengan membatasi pada n baris". Saya akhirnya membaca pertanyaan di sini ketika saya mencoba membatasi hingga 1 baris dan menemukan solusi yang lebih mudah. Saya pikir orang lain mungkin berakhir di sini mencari untuk membatasi EditText mereka ke 1 baris dan menerapkan "pembatas baris khusus". Jawaban saya ada di sini untuk pengguna SO lainnya yang akhirnya mencari pertanyaan ini karena alasan yang sama saya lakukan.
Jesse Black

@ IndrekKõue yang seharusnya tidak terlalu sulit.
Don Larynx

10
singleLine sudah tidak digunakan lagi
Ali

1
Atribut editText singleLine = "true" sudah usang dan akan crash di Perangkat yang menggunakan Android lebih besar dari 7,0
TranHieu

24

@Cedekasem Anda benar, tidak ada "pembatas baris" bawaan. Tapi saya membangun satu diri saya, jadi jika ada yang tertarik kode di bawah ini. Bersulang.

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

Ini memiliki efek samping yang tidak intuitif untuk pengguna. mis. jika Anda memiliki 7 baris di EditText Anda dan kemudian tekan enter di tengahnya, maka Anda dapat mengucapkan selamat tinggal pada baris terakhir teks Anda.
miguel.martin

tidak akan berfungsi jika Anda menempelkan lebih dari teks maxlines ke dalamnya. Jadi lebih baik menggunakan addTextChangedListener.
Kuldeep Sakhiya

13

Saya melakukan sesuatu seperti yang kalian cari. Ini LimitedEditTextkelas saya .

Fitur:

  • Anda dapat membatasi jumlah baris dalam komponen LimitedEditText Anda
  • Anda dapat membatasi jumlah karakter dalam komponen LimitedEditText Anda
  • jika Anda melebihi batas karakter atau garis di suatu tempat di tengah teks, kursor
    tidak akan membawa Anda sampai akhir - itu akan tetap berada di tempat Anda berada.

Saya mematikan pendengar, karena setiap panggilan setText()metode akan memanggil 3 metode panggilan balik ini secara berjaga-jaga jika pengguna melebihi karakter atau batas baris.

Kode:

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
Solusi ini sangat sederhana dan elegan! Terima kasih
GuilhE

Saya gunakan beforeCursorPosition = getSelectionStart();di afterTextChangedcallback. Ini berfungsi lebih baik karena ketika mengetik esetelah mengetik abcd, EditText mungkin 'berpikir' Anda ganti abcddengan abcde, karena alasan metode input.
hanswim

11

Saya telah membuat solusi yang lebih sederhana untuk ini: 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);
        }
    });

Anda dapat mengubah nilai 3 in txtSpecialRequests.getLineCount() > 3ke kebutuhan Anda.


3
Terima kasih banyak, akhirnya berhasil setelah beberapa solusi yang salah. Ini harus menjadi jawaban yang diterima.
eyadMhanna

Saya mendapatkan bahwa "txtSpecialRequests" adalah wadah EditText Anda, tetapi di mana Anda mengatur variabel lastSpecialRequestsCursorPosition dan specialRequests?
drearypanoramic

tentu saja di luar metode ini :) init lastSpecialRequestsCursorPosition = 0 dan specialRequests = ""
Oscar Yuandinata

Solusi bagus!
Marcus

5

Berikut ini adalah InputFilter yang membatasi garis yang diizinkan dalam 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;
  }
}

Untuk menambahkannya ke EditText:

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

Solusi yang bagus, namun ini membahas masalah pembungkusan teks (tidak masuk)
Peter File

4

Inilah yang saya gunakan dalam proyek saya:

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

Dan itu berhasil di semua skenario


1
Apa konteks yang dibutuhkan TextWatcher? KeyListener itu yang saya butuhkan.
AlanKley

@AlanKley: Kita perlu sebelum dan sesudah teks mengubah acara untuk menghitung jumlah baris editText. Seolah-olah kita terus memasukkan teks dan tidak menekan tombol "baris baru" maka onKey tidak dipecat dan kursor pindah ke baris berikutnya secara otomatis. Jadi untuk melacak garis semacam ini kita perlu textWatcher. Saya harap saya bisa membuat Anda mengerti.
Bajak laut

Saya melihat. Terima kasih atas klarifikasi itu.
AlanKley

@AlanKley Jika menurut Anda jawaban saya bermanfaat, silakan pilih.
Bajak Laut

public void afterTextChanged (Editable arg0) {int lineCount = editText.getLineCount (); if (lineCount> numberOfLines) {editText.setText (teks); }} akan melempar StackOverflowException ...
desgraci


3

Solusi paling sederhana:

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

ini adalah satu pendekatan. Bisa membantu seseorang.

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

1

Cara lain untuk membatasi Anda EditTextke satu baris adalah sebagai berikut:

editText2.setTransformationMethod(new SingleLineTransformationMethod());

Perhatikan bahwa setelah menerapkan metode transformasi ini, tombol enter menciptakan spasi ketika ditekan. Itu masih memenuhi pertanyaan TS.


Cara yang bagus untuk menyembunyikan baris baru! Namun, dalam nilainya, masih akan ada karakter 'baris baru' !!
Gregory Stein

1

Anda dapat membatasi teks Anda sesuai dengan jumlah baris Anda, saya katakan sekitar 37 huruf dalam satu baris

<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 () adalah salah satu opsi; jika Anda menginginkan nilai bukan nol, pastikan tampilan Anda diukur. Untuk keyboard lunak onKeyListener tidak akan berfungsi sehingga Anda harus menambahkan addTextChangedListener () yang akan melacak perubahan teks saat Anda mengetik. Segera setelah Anda mendapatkan cukup banyak baris di dalam punggung panggilannya, lakukan apa pun yang ingin Anda batasi: hapus karakter dengan getText (), setText () atau sesuatu yang lebih mewah. Anda bahkan dapat membatasi jumlah karakter menggunakan filter.

Pilihan lain adalah memantau ukuran teks dengan getLineBounds (). Ini akan berinteraksi dengan gravitasi teks / paddign jadi hati-hati.


0

Untuk membatasi jumlah karakter, kita cukup menggunakan properti maxLength dari EditText karena tidak akan mengizinkan pengguna untuk memasukkan lebih banyak karakter.


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

Gagasan lain: setiap kali setelah mengetik, teks baru akan disimpan ke String lastText, hanya jika jumlah baris tidak melebihi MAX_LINES. Jika ya, kami akan mengatur teks EditText ke teks yang terakhir ditambahkan (sehingga perubahan akan dihapus) dan memberi tahu pengguna untuk membuatnya singkat.

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

Ini adalah perpanjangan dari jawaban Indrek Kõue untuk 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

Coba gunakan kombinasi atribut EditText berikut di dalam file xml:

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


2
Hanya kepala. singleLine sudah tidak digunakan lagi. maxLines diperkenalkan sebagai pengganti singleLine.
Sandeep R

@SandeepR Anda salah, android:inputTypemengganti penggunaanandroid:singleLine
Pierre
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.