EditText maxLines çalışmıyor - kullanıcı yine de ayarlanandan daha fazla satır girebilir


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

Kullanıcı, enter / sonraki satır tuşuna basarak 5'ten fazla satır girebilir. EditText ile kullanıcı girişini sabit sayıda satırla nasıl sınırlayabilirim?


Yanıtlar:


85

Öznitelik maxLinesmaksimum yüksekliğine karşılık gelir EditText, iç metin satırlarını değil dış sınırları kontrol eder.


Ben de öyle düşündüm ... Girilen satırları sınırlamanın bir yolu var mı yoksa programlı olarak arka uç kodunda buna sahip miyim?
Indrek Kõue

Girilen satırları istediğiniz gibi sınırlamanın basit bir yolu yoktur. Bunu kodunuzda manuel olarak yapmanız gerekecek.
Cedekasme

3
Bir geliştirici için "maxLines", editText ile mümkün olması gereken maksimum satır sayısını ifade eder. Sadece belirli bir yükseklik isteseydim, "çizgiler" kullanırdım. : - /
Someone Somewhere

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

"İnputType" özelliğinin ayarlandığından emin olmanız yeterlidir. Bu çizgi olmadan çalışmaz.

android:inputType="text"

3
@Neol Chew Haklısın! Ben ayarladıktan sonra çalıştı inputTypeetmek text.
Zamanımı

6
@byJeevan, her zaman inputType'ın varsayılan bir "text" değeri olduğunu düşünmüşümdür. Sanırım yanılmışım.
Noel Chew

2
Metnin inputType için ayarlanan varsayılan değer olmaması çok tuhaf, Yine de Harika Cevap
Muhammed Refaat

9
yalnızca 1'lik maxLines için çalışıyor ancak yeni satır ekleyemezsiniz
Daniel Raouf

69

Bu, n satırla sınırlama genel sorununu çözmez. EditText'inizi yalnızca 1 satır metin alacak şekilde sınırlamak istiyorsanız, bu çok kolay olabilir.
Bunu xml dosyasında ayarlayabilirsiniz.

android:singleLine="true"

veya programlı olarak

editText.setSingleLine(true);

8
ama ya 2 satırla sınırlamak istiyorsanız? veya 3? Bunun için özel sıra sınırlayıcı
yapmalısınız

4
Bunun farkındayım. "Bu, n satırla sınırlama genel sorununu çözmez". 1 satır ile sınırlamaya çalışırken ve daha kolay bir çözüm bulmaya çalışırken buradaki soruyu okudum. Başkalarının burada EditText'lerini 1 satırla sınırlandırmak ve "özel satır sınırlayıcı" yı uygulamak isteyebileceğini düşündüm. Cevabım, benim yaptığım sebeple bu soruyu arayan diğer SO kullanıcıları için burada.
Jesse Black

@ IndrekKõue bu çok zor olmamalı.
Don Larynx

10
singleLine kullanımdan kaldırıldı
Ali

1
editText'in özelliği singleLine = "true" kullanımdan kaldırıldı ve 7.0'dan daha büyük Android'de kullanılan Cihazlarda kilitlenecek
TranHieu

24

@Cedekasem haklısınız, yerleşik bir "satır sınırlayıcı" yok. Ama ben bir tane yaptım, bu yüzden ilgilenen varsa kod aşağıdadır. Şerefe.

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

Bunun kullanıcı için sezgisel olmayan bir yan etkisi vardır. Örneğin, Düzenleme Metninizde 7 satırınız varsa ve ardından ortasında enter tuşuna basarsanız, metninizin son satırına güle güle diyebilirsiniz.
miguel.martin

maxlines metninden fazlasını yapıştırırsanız çalışmaz. AddTextChangedListener kullanmak daha iyi olur.
Kuldeep Sakhiya

13

Sizin aradığınız gibi bir şey yaptım. İşte benim LimitedEditTextsınıfım.

Özellikleri:

  • LimitedEditText bileşeninizdeki satır sayısını sınırlayabilirsiniz
  • LimitedEditText bileşeninizdeki karakter sayısını sınırlayabilirsiniz
  • Metnin ortasında bir yerde karakter veya satır sınırını aşarsanız, imleç
    sizi sona götürmez - bulunduğunuz yerde kalır.

Dinleyiciyi kapatıyorum, çünkü her setText()yöntem çağrısı, kullanıcının karakter veya satır sınırını aşması durumunda bu 3 geri çağrı yöntemini özyinelemeli olarak çağırır.

Kod:

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
Bu çözüm çok basit ve zarif! Teşekkürler
GuilhE

Kullandığım beforeCursorPosition = getSelectionStart();içinde afterTextChangedcallback'inde. Daha iyi çalışır çünkü yazdıktan esonra yazarken abcd, giriş yöntemi nedeniyle EditText abcdile değiştireceğinizi 'düşünebilir' abcde.
hanswim

11

Bunun için daha basit bir çözüm yaptım: 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);
        }
    });

3 in değerini txtSpecialRequests.getLineCount() > 3ihtiyaçlarınıza göre değiştirebilirsiniz.


3
Çok teşekkür ederim, sonunda birçok yanlış çözümün ardından çalıştı. Kabul edilen cevap bu olmalıdır.
eyadMhanna

"TxtSpecialRequests" öğesinin EditText kabınız olduğunu anlıyorum, ancak lastSpecialRequestsCursorPosition ve specialRequests değişkenlerini nereye ayarlarsınız?
drearypanoramic

elbette bu yöntemin dışında :) init lastSpecialRequestsCursorPosition = 0 ve specialRequests = ""
Oscar Yuandinata

Harika çözüm!
Marcus

5

İşte EditText'te izin verilen satırları sınırlayan bir InputFilter:

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

EditText'e eklemek için:

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

İyi bir çözüm, ancak metin sarma (
Peter File

4

Projemde kullandığım şey bu:

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

Ve tüm senaryolarda çalıştı


1
TextWatcher hangi bağlamda gereklidir? KeyListener tek ihtiyacım olan şeydi.
AlanKley

@AlanKley: editText satırlarının sayısını hesaplamak için metin olaylarından önce ve sonra ihtiyacımız var. Metin girmeye devam ediyor ve "yeni satır" tuşuna basmıyorsak, onKey ateşlenmiyor ve imleç otomatik olarak sonraki satıra hareket ediyor. Bu tür satırları takip etmek için textWatcher'a ihtiyacımız var. Umarım anlamanı sağlayabilirim.
Korsan

Anlıyorum. Açıklama için teşekkürler.
AlanKley

@AlanKley Cevabımın yararlı olduğunu düşünüyorsanız, lütfen oy verin.
Korsan

public void afterTextChanged (Düzenlenebilir arg0) {int lineCount = editText.getLineCount (); if (lineCount> numberOfLines) {editText.setText (metin); }} bir StackOverflowException ...
desgraci


3

En basit çözüm:

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

bu bir yaklaşımdır. Birine yardımcı olabilir.

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

1

Numaranızı EditTextbir satırla sınırlamanın başka bir yolu şudur:

editText2.setTransformationMethod(new SingleLineTransformationMethod());

Bu dönüştürme yöntemini uyguladıktan sonra, enter tuşuna basıldığında boşluklar oluşturduğuna dikkat edin. Bu hala TS'nin sorusunu tatmin ediyor.


Yeni satırı saklamanın güzel yolu! Değerde, ancak yine de bir 'yeni satır' karakteri olacaktır !!
Gregory Stein

1

Tek satırda 37 alfabe dediğim satır sayınıza göre metninizi sınırlayabilirsiniz

<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 () bir seçenektir; sıfır olmayan değerler istiyorsanız, görünümünüzün ölçüldüğünden emin olun. Yazılım klavyesi için onKeyListener çalışmaz, bu nedenle siz yazarken metin değişikliklerini izleyecek addTextChangedListener () eklemeniz gerekir. Geri aramalarında yeterince satır alır almaz, sınırlamak istediğinizi yapın: getText (), setText () veya daha süslü bir şey ile karakterleri silin. Hatta bir filtre kullanarak karakter sayısını sınırlayabilirsiniz.

Diğer bir seçenek de metnin boyutunu getLineBounds () ile izlemektir. Bu, metin yerçekimi / paddign ile etkileşime girecektir, bu yüzden dikkatli olun.


0

Sınırlı karakter sayısı için, kullanıcının daha fazla karakter girmesine izin vermeyeceğinden, EditText'in maxLength özelliğini kullanabiliriz.


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

Başka bir fikir: Her yazdıktan sonra, yeni metin yalnızca satır sayısı MAX_LINES'i aşmıyorsa String lastText'e kaydedilir. Varsa, EditText metnini son eklenen metne ayarlar (böylece değişiklikler silinir) ve kullanıcıyı kısa tutması için bilgilendiririz.

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

Bu, Indrek Kõue'nun Kotlin'e cevabının bir uzantısıdır

                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

Xml dosyası içindeki EditText özniteliklerinin aşağıdaki kombinasyonunu kullanmayı deneyin:

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


2
Sadece aklınızda bulunsun. singleLine kullanımdan kaldırıldı. maxLines, singleLine yerine tanıtıldı.
Sandeep R

@SandeepR Yanılıyorsunuz, android:inputTypekullanımının yerini alıyorandroid:singleLine
Pierre
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.