EditText maxLines không hoạt động - người dùng vẫn có thể nhập nhiều dòng hơn đặt


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

Người dùng có thể nhập hơn 5 dòng, bằng cách nhấn phím nhập / hàng tiếp theo. Làm cách nào tôi có thể giới hạn đầu vào của người dùng ở số lượng hàng cố định với EditText?


Câu trả lời:


84

Thuộc tính maxLinestương ứng với chiều cao tối đa của EditTextnó, nó kiểm soát các ranh giới bên ngoài và không phải các dòng văn bản bên trong.


Đó cũng là những gì tôi nghĩ ... Có cách nào để hạn chế các dòng đầu vào hay tôi phải sử dụng nó trên mã phụ trợ theo chương trình?
Indrek Kõue

Không có cách đơn giản để giới hạn các dòng đầu vào như bạn muốn. Bạn sẽ phải làm điều đó bằng tay trong mã của bạn.
Cedekasme

3
Tôi nghĩ với một nhà phát triển "maxLines" ngụ ý số lượng dòng tối đa có thể có với một chỉnh sửa. Nếu tôi chỉ muốn một chiều cao cụ thể, tôi sẽ sử dụng "đường". : - /
Ai đó ở đâu đó

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

Bạn chỉ cần đảm bảo rằng bạn đã đặt thuộc tính "inputType". Nó không hoạt động mà không có dòng này.

android:inputType="text"

3
@Neol Nhai Bạn nói đúng! Tôi làm việc sau khi cài đặt inputTypeđể text. Cảm ơn vì đã tiết kiệm thời gian của tôi :-)
byJeevan

6
@byJeevan, tôi luôn nghĩ inputType có giá trị mặc định là "văn bản". Đoán tôi đã sai.
Noel nhai

2
Rất kỳ lạ khi Văn bản không phải là giá trị mặc định được đặt cho inputType, Câu trả lời tuyệt vời
Muhammed Refaat

9
nó chỉ hoạt động với maxLines 1 nhưng bạn không thể thêm dòng mới
Daniel Raouf

68

Điều này không giải quyết được vấn đề chung về việc giới hạn n dòng. Nếu bạn muốn giới hạn EditText của mình chỉ lấy 1 dòng văn bản, điều này có thể rất dễ dàng.
Bạn có thể đặt cái này trong tệp xml.

android:singleLine="true"

hoặc lập trình

editText.setSingleLine(true);

8
Nhưng nếu bạn muốn giới hạn ở 2 hàng thì sao? hay 3? Vì vậy, bạn phải xây dựng bộ giới hạn hàng tùy chỉnh ...
Indrek Kõue

4
Tôi biết điều đó. "Điều này không giải quyết được vấn đề chung về việc giới hạn n dòng". Tôi đã kết thúc việc đọc qua câu hỏi ở đây trong khi tôi đang cố gắng giới hạn ở 1 dòng và tìm thấy một giải pháp dễ dàng hơn. Tôi hình dung những người khác có thể kết thúc ở đây đang tìm cách giới hạn EditText của họ thành 1 dòng và thực hiện "bộ giới hạn hàng tùy chỉnh". Câu trả lời của tôi là ở đây cho những người dùng SO khác, những người cuối cùng tìm kiếm câu hỏi này với cùng lý do tôi đã làm.
Jesse Black

@ IndrekKõue không nên quá khó.
Don Larynx

10
SingleLine không được dùng nữa
Ali

1
thuộc tính của chỉnh sửa singleLine = "true" không được dùng nữa và nó sẽ bị sập tại các Thiết bị đang sử dụng tại Android lớn hơn 7.0
TranHieu

24

@Cedekasem bạn nói đúng, không có "giới hạn hàng" tích hợp. Nhưng tôi đã tự xây dựng một cái cho riêng mình, vì vậy nếu có ai quan tâm thì mã bên dưới. Chúc mừng.

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

Điều này có tác dụng phụ không trực quan cho người dùng. ví dụ: nếu bạn có 7 dòng trong EditText và sau đó nhấn enter ở giữa nó, thì bạn có thể nói tạm biệt với dòng cuối cùng của văn bản.
Miguel.martin

Sẽ không hoạt động nếu bạn dán nhiều hơn văn bản tối đa vào nó. Vì vậy, tốt hơn là sử dụng addTextChangedListener.
Kuldeep Sakhiya

13

Tôi đã làm một cái gì đó giống như các bạn đã tìm kiếm. Đây là LimitedEditTextlớp học của tôi .

Đặc trưng:

  • bạn có thể giới hạn số dòng trong thành phần LimitedEditText của mình
  • bạn có thể giới hạn số lượng ký tự trong thành phần LimitedEditText của mình
  • nếu bạn vượt quá giới hạn ký tự hoặc dòng ở đâu đó ở giữa văn bản, con trỏ
    sẽ không đưa bạn đến cuối - nó sẽ ở lại nơi bạn đã ở.

Tôi đang tắt người nghe, bởi vì mọi cuộc gọi của setText()phương thức sẽ gọi đệ quy 3 phương thức gọi lại này trong trường hợp khi người dùng vượt quá giới hạn ký tự hoặc dòng.

Mã số:

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
Giải pháp này rất đơn giản và thanh lịch! Cảm ơn
GuilhE

Tôi sử dụng beforeCursorPosition = getSelectionStart();trong afterTextChangedgọi lại. Nó hoạt động tốt hơn vì khi gõ esau khi gõ abcd, các EditText thể 'nghĩ' bạn thay thế abcdvới abcde, vì phương thức nhập lý do.
hanswim 17/07/19

11

Tôi đã thực hiện giải pháp đơn giản hơn cho việc này: 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);
        }
    });

Bạn có thể thay đổi giá trị của 3 trong txtSpecialRequests.getLineCount() > 3nhu cầu của bạn.


3
Cảm ơn bạn rất nhiều, cuối cùng đã làm việc sau nhiều giải pháp sai. Đây phải là câu trả lời được chấp nhận.
EyadMhanna

Tôi nhận được rằng "txtecialRequests" là thùng chứa EditText của bạn, nhưng nơi bạn đặt các biến cuối cùng SpecialRequestsC tiềnP vị trí và SpecialRequests?
drearypanoramic

bên ngoài phương pháp này tất nhiên :) init lastecialRequestsCoderP vị trí = 0 và SpecialRequests = ""
Oscar Yuandinata

Giải pháp tuyệt vời!
Marcus

5

Dưới đây là InputFilter giới hạn các dòng được phép trong 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;
  }
}

Để thêm nó vào EditText:

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

Giải pháp tốt, tuy nhiên, nó giải quyết vấn đề gói văn bản (không nhập)
Peter File

4

Đây là những gì tôi đã sử dụng trong dự án của tôi:

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

Và nó đã làm việc trong tất cả các kịch bản


1
TextWatcher cần bối cảnh nào? KeyListener là tất cả những gì tôi cần.
AlanKley

@AlanKley: Chúng tôi cần trước và sau khi văn bản thay đổi các sự kiện để tính toán số dòng chỉnh sửa. Như thể chúng ta tiếp tục nhập văn bản và không nhấn phím "dòng mới" thì onKey không được kích hoạt và con trỏ tự động chuyển sang dòng tiếp theo. Vì vậy, để theo dõi các loại đường này, chúng ta cần textWatcher. Tôi hy vọng tôi có thể làm cho bạn hiểu.
Cướp biển

Tôi hiểu rồi. Cảm ơn đã làm rõ.
AlanKley

@AlanKley Nếu bạn nghĩ câu trả lời của tôi hữu ích thì hãy bỏ phiếu cho nó.
Cướp biển

công khai void afterTextChanged (Có thể chỉnh sửa arg0) {int lineCount = editText.getLineCount (); if (lineCount> numberOfLines) {editText.setText (văn bản); }} sẽ ném một StackOverflowException ...
desgraci


3

Giải pháp đơn giản nhất:

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

đây là một cách tiếp cận Có thể giúp ai đó.

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

1

Một cách khác để giới hạn EditTextmột dòng của bạn là như sau:

editText2.setTransformationMethod(new SingleLineTransformationMethod());

Lưu ý rằng sau khi áp dụng phương thức chuyển đổi này, phím enter sẽ tạo khoảng trắng khi nhấn. Điều đó vẫn thỏa mãn câu hỏi của TS.


Cách tốt đẹp để ẩn dòng mới! Tuy nhiên, trong giá trị, vẫn sẽ có một ký tự 'dòng mới' !!
Gregory Stein

1

Bạn có thể giới hạn văn bản của mình theo số dòng của bạn, tôi nói khoảng 37 bảng chữ cái trong một dòng

<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 () là một tùy chọn; nếu bạn muốn các giá trị khác không, hãy đảm bảo rằng chế độ xem của bạn được đo. Đối với bàn phím mềm, onKeyListener sẽ không hoạt động, do đó bạn phải thêm addTextChangedListener () sẽ theo dõi các thay đổi văn bản khi bạn nhập. Ngay khi bạn nhận được đủ các dòng bên trong các cuộc gọi trở lại, hãy làm bất cứ điều gì bạn muốn để hạn chế nó: xóa các ký tự bằng getText (), setText () hoặc một cái gì đó lạ mắt hơn. Bạn thậm chí có thể giới hạn số lượng ký tự bằng bộ lọc.

Một tùy chọn khác là theo dõi kích thước của văn bản với getLineBound (). Điều này sẽ tương tác với trọng lực văn bản / paddign vì vậy hãy cẩn thận.


0

Đối với số lượng ký tự giới hạn, chúng ta chỉ cần sử dụng thuộc tính maxLạng của EditText vì nó sẽ không cho phép người dùng nhập thêm ký tự.


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

Một ý tưởng khác: mỗi lần sau khi gõ, văn bản mới sẽ được lưu vào Chuỗi cuối, chỉ khi số lượng dòng không vượt quá MAX_LINES. Nếu đúng như vậy, chúng tôi sẽ đặt văn bản của EditText thành văn bản được thêm vào lần cuối (để thay đổi sẽ bị xóa) và thông báo cho người dùng để giữ cho nó ngắn.

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

Đây là phần mở rộng của câu trả lời của Indrek Kõue cho 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

Hãy thử sử dụng kết hợp các thuộc tính sau của EditText bên trong tệp xml:

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


2
Chỉ cần một cái đầu lên. SingleLine không được dùng nữa. maxLines đã được giới thiệu thay cho SingleLine.
Sandeep R

@SandeepR Bạn đã sai, android:inputTypethay thế việc sử dụngandroid:singleLine
Pierre
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.