EditText maxLines ไม่ทำงาน - ผู้ใช้ยังสามารถป้อนข้อมูลได้มากกว่าที่กำหนด


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

ผู้ใช้สามารถป้อนข้อมูลได้มากกว่า 5 บรรทัดโดยกดปุ่ม enter / next row ฉันจะ จำกัด การป้อนข้อมูลของผู้ใช้เป็นจำนวนแถวคงที่ด้วย EditText ได้อย่างไร


ดูโพสต์นี้: stackoverflow.com/questions/14672234/…
ali safaei

คำตอบ:


85

แอตทริบิวต์maxLinesสอดคล้องกับความสูงสูงสุดของEditTextมันควบคุมขอบเขตภายนอกไม่ใช่บรรทัดข้อความภายใน


นั่นคือสิ่งที่ฉันคิดเช่นกัน ... มีวิธี จำกัด บรรทัดที่ป้อนหรือฉันต้องใช้โค้ดแบ็กเอนด์โดยใช้โปรแกรมหรือไม่?
Indrek Kõue

ไม่มีวิธีง่ายๆในการ จำกัด บรรทัดที่ป้อนอย่างที่คุณต้องการ คุณจะต้องดำเนินการด้วยตนเองในโค้ดของคุณ
Cedekasme

3
ฉันคิดว่าสำหรับนักพัฒนา "maxLines" หมายถึงจำนวนบรรทัดสูงสุดที่ควรจะเป็นไปได้ด้วย editText ถ้าฉันต้องการความสูงที่เฉพาะเจาะจงฉันจะใช้ "เส้น" : - /
ใครสักคน

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

คุณต้องแน่ใจว่าคุณได้ตั้งค่าแอตทริบิวต์ "inputType" แล้ว มันใช้ไม่ได้ถ้าไม่มีบรรทัดนี้

android:inputType="text"

3
@Neol Chew คุณพูดถูก! ฉันทำงานหลังจากตั้งค่าinputTypeเป็นtext. ขอบคุณที่ช่วยประหยัดเวลา :-)
Jeevan

6
@byJeevan ฉันคิดเสมอว่า inputType มีค่าเริ่มต้นเป็น "text" เดาว่าฉันคิดผิด
Noel Chew

2
แปลกมากที่ข้อความไม่ใช่ค่าเริ่มต้นที่ตั้งไว้สำหรับ inputType คำตอบที่ดีแม้ว่า
Muhammed Refaat

9
ใช้งานได้กับ maxLines ที่ 1 เท่านั้น แต่คุณไม่สามารถเพิ่มบรรทัดใหม่ได้
Daniel Raouf

69

สิ่งนี้ไม่ได้แก้ปัญหาทั่วไปของการ จำกัด n บรรทัด หากคุณต้องการ จำกัด EditText ให้ใช้ข้อความเพียง 1 บรรทัดอาจเป็นเรื่องง่ายมาก
คุณสามารถตั้งค่านี้ในไฟล์ xml

android:singleLine="true"

หรือโดยทางโปรแกรม

editText.setSingleLine(true);

8
แต่ถ้าคุณต้องการ จำกัด 2 แถวล่ะ? หรือ 3? เพื่อที่คุณจะต้องสร้างตัว จำกัด แถวที่กำหนดเอง ...
Indrek Kõue

4
ฉันตระหนักถึงสิ่งนั้น "นี่ไม่ได้แก้ปัญหาทั่วไปของการ จำกัด n บรรทัด" ฉันอ่านคำถามที่นี่ในขณะที่ฉันพยายาม จำกัด ให้เหลือ 1 บรรทัดและพบวิธีแก้ปัญหาที่ง่ายกว่า ฉันคิดว่าคนอื่น ๆ อาจลงเอยที่นี่โดยต้องการ จำกัด EditText ไว้ที่ 1 บรรทัดและใช้ "ตัว จำกัด แถวที่กำหนดเอง" คำตอบของฉันอยู่ที่นี่สำหรับผู้ใช้ SO รายอื่นที่ค้นหาคำถามนี้ด้วยเหตุผลเดียวกับที่ฉันทำ
Jesse Black

@ IndrekKõueที่ไม่ควรจะยากเกินไป
Don Larynx

10
singleLine เลิกใช้งานแล้ว
Ali

1
แอตทริบิวต์ singleLine = "true" ของ editText เลิกใช้งานแล้วและจะขัดข้องที่อุปกรณ์ที่ใช้ Android ที่ใหญ่กว่า 7.0
TranHieu

24

@Cedekasem คุณพูดถูกไม่มี "แถว จำกัด " ในตัว แต่ฉันสร้างขึ้นมาเองดังนั้นหากใครสนใจรหัสอยู่ด้านล่าง ไชโย

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

สิ่งนี้มีผลข้างเคียงที่ไม่ใช้งานง่ายสำหรับผู้ใช้ เช่นถ้าคุณมี 7 บรรทัดใน EditText ของคุณแล้วกด Enter ตรงกลางคุณสามารถบอกลาก่อนที่บรรทัดสุดท้ายของข้อความของคุณ
miguel.martin

จะไม่ทำงานหากคุณวางข้อความมากกว่า maxlines ลงไป ดังนั้นจะดีกว่าที่จะใช้ addTextChangedListener
Kuldeep Sakhiya

13

ฉันทำบางอย่างเหมือนที่พวกคุณมองหา นี่คือLimitedEditTextชั้นเรียนของฉัน

คุณสมบัติ:

  • คุณสามารถ จำกัด จำนวนบรรทัดในคอมโพเนนต์ LimitedEditText ของคุณ
  • คุณสามารถ จำกัด จำนวนอักขระในคอมโพเนนต์ LimitedEditText ของคุณ
  • ถ้าคุณมีอักขระหรือบรรทัดที่อยู่ตรงกลางข้อความเกินขีด จำกัด ให้เคอร์เซอร์
    จะไม่นำคุณไปที่จุดสิ้นสุด - มันจะอยู่ในที่ที่คุณเคยอยู่

ฉันปิดฟังเพราะทุกสายของ setText()วิธีการจะเรียกวิธีการโทรกลับ 3 วิธีนี้ซ้ำในกรณีที่ผู้ใช้เกินขีด จำกัด อักขระหรือบรรทัด

รหัส:

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
วิธีนี้ง่ายและสง่างามมาก! ขอบคุณ
GuilhE

ฉันใช้beforeCursorPosition = getSelectionStart();ในการafterTextChangedโทรกลับ ทำงานได้ดีขึ้นเนื่องจากเมื่อพิมพ์eหลังจากพิมพ์abcdEditText อาจ 'คิดว่า' คุณแทนที่abcdด้วยabcdeเนื่องจากเหตุผลวิธีการป้อนข้อมูล
hanswim

11

ฉันได้แก้ปัญหาที่ง่ายกว่านี้: 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 นิ้วtxtSpecialRequests.getLineCount() > 3ตามความต้องการของคุณ


3
ขอบคุณมากในที่สุดก็ทำงานได้หลังจากแก้ปัญหาผิดหลายครั้ง นี่ควรเป็นคำตอบที่ได้รับการยอมรับ
eyadMhanna

ฉันเข้าใจว่า "txtSpecialRequests" เป็นคอนเทนเนอร์ EditText ของคุณ แต่คุณจะตั้งค่าตัวแปร lastSpecialRequestsCursorPosition และ specialRequests ไว้ที่ใด
drearypanoramic

นอกวิธีนี้แน่นอน :) init lastSpecialRequestsCursorPosition = 0 และ specialRequests = ""
Oscar Yuandinata

ทางออกที่ดี!
Marcus

5

นี่คือ InputFilter ที่ จำกัด บรรทัดที่อนุญาตใน 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;
  }
}

ในการเพิ่มลงใน EditText:

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

ทางออกที่ดีอย่างไรก็ตามมันช่วยแก้ปัญหาการตัดข้อความ (ไม่ใส่)
Peter File

4

นี่คือสิ่งที่ฉันใช้ในโครงการของฉัน:

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

และใช้งานได้ในทุกสถานการณ์


1
TextWatcher ต้องการบริบทใด KeyListener คือทั้งหมดที่ฉันต้องการ
AlanKley

@AlanKley: เราต้องการก่อนและหลังข้อความที่เปลี่ยนแปลงเหตุการณ์เพื่อคำนวณจำนวนบรรทัดของ editText ราวกับว่าเราป้อนข้อความไปเรื่อย ๆ และไม่ได้กดปุ่ม "บรรทัดใหม่" จากนั้น onKey จะไม่ทำงานและเคอร์เซอร์จะย้ายไปที่บรรทัดถัดไปโดยอัตโนมัติ ดังนั้นในการติดตามบรรทัดประเภทนี้เราต้องใช้ textWatcher ฉันหวังว่าฉันจะสามารถทำให้คุณเข้าใจ
Pirate

ฉันเห็น. ขอบคุณสำหรับคำชี้แจงนั้น
AlanKley

@AlanKley ถ้าคุณคิดว่าคำตอบของฉันมีประโยชน์โปรดโหวตให้
Pirate

โมฆะสาธารณะ afterTextChanged (แก้ไขได้ arg0) {int lineCount = editText.getLineCount (); ถ้า (lineCount> numberOfLines) {editText.setText (ข้อความ); }} จะโยน StackOverflowException ...
desgraci


3

วิธีแก้ปัญหาที่ง่ายที่สุด:

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



1

อีกวิธีหนึ่งในการ จำกัดEditTextหนึ่งบรรทัดมีดังต่อไปนี้:

editText2.setTransformationMethod(new SingleLineTransformationMethod());

โปรดทราบว่าหลังจากใช้วิธีการแปลงนี้แล้วปุ่ม Enter จะสร้างช่องว่างเมื่อกด นั่นยังคงตอบสนองคำถามของ TS


วิธีที่ดีในการซ่อนบรรทัดใหม่! อย่างไรก็ตามในมูลค่าจะยังคงมีตัวละคร 'บรรทัดใหม่' อยู่ !!
Gregory Stein

1

คุณสามารถ จำกัด ข้อความของคุณตามจำนวนบรรทัดของคุณฉันพูดประมาณ 37 ตัวอักษรในหนึ่งบรรทัด

<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 () เป็นทางเลือกหนึ่ง; หากคุณต้องการค่าที่ไม่ใช่ศูนย์ให้ตรวจสอบว่ามีการวัดมุมมองของคุณ สำหรับซอฟต์คีย์บอร์ด onKeyListener จะไม่ทำงานดังนั้นคุณต้องเพิ่ม addTextChangedListener () ที่จะติดตามการเปลี่ยนแปลงข้อความขณะที่คุณพิมพ์ ทันทีที่คุณได้รับสายเพียงพอในการโทรกลับให้ทำทุกอย่างที่คุณต้องการ จำกัด : ลบอักขระด้วย getText (), setText () หรือสิ่งที่แปลกใหม่กว่า คุณสามารถ จำกัด จำนวนอักขระโดยใช้ตัวกรอง

อีกทางเลือกหนึ่งคือการตรวจสอบขนาดของข้อความด้วย getLineBounds () สิ่งนี้จะโต้ตอบกับแรงโน้มถ่วงของข้อความ / พายเรือดังนั้นโปรดใช้ความระมัดระวัง


0

สำหรับจำนวนอักขระที่ จำกัด เราสามารถใช้คุณสมบัติ maxLength ของ EditText ได้เนื่องจากจะไม่อนุญาตให้ผู้ใช้ป้อนอักขระเพิ่มเติม


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

แนวคิดอื่น: ทุกครั้งหลังจากพิมพ์ข้อความใหม่จะถูกบันทึกลงใน String lastText เฉพาะในกรณีที่จำนวนบรรทัดไม่เกิน MAX_LINES หากเป็นเช่นนั้นเราจะตั้งค่าข้อความ EditText เป็นข้อความที่เพิ่มล่าสุด (ดังนั้นการเปลี่ยนแปลงจะถูกลบออก) และแจ้งให้ผู้ใช้ทราบเพื่อให้สั้น

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

นี่คือส่วนขยายของคำตอบของIndrek Kõueสำหรับ 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

ลองใช้แอตทริบิวต์ต่อไปนี้ของ EditText ภายในไฟล์ xml:

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


2
เพียงแค่หัวขึ้น singleLine เลิกใช้งานแล้ว maxLines ถูกนำมาใช้แทน singleLine
Sandeep R

@SandeepR คุณคิดผิดandroid:inputTypeแทนที่การใช้android:singleLine
ปิแอร์
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.