EditText限制最大输入行数完美实现

问题描述

在开发中可能会遇到这样的需求:
限制输入框的输入,但是不限制具体输入字符个数,而是限制最多输入行数,当大于n行时自动截断多余的字符,用户再次输入就不会有反应。

具体可能还分两种情况:
第一种:输入框宽度固定,限制最多输入n行字符。
效果如下:
在这里插入图片描述
第二种:输入框宽度不固定,一开始设置一个最小宽度,当输入文字大于这个宽度时则动态增加输入框宽度,当宽度大于最大宽度时则换行,而且同样限制最多输入n行字符。
效果如下:
在这里插入图片描述

具体实现

输入框宽度固定

当EditText的宽度是一个具体尺寸或者match_parent时实现比较简单。
思路:监听输入框的文字变化,当行数大于n行时则删除多余的字符。
核心代码:

	@Override
	public void onTextChanged(CharSequence s, int start, int before, int count) {
	    int lineCount = getLineCount();
	    if (lineCount > MAX_INPUT_LINES) {
	        //发现输入的内容大于最大行数,则删除多余的内容
	        deleteExtra();
	    }
	}
	private void deleteExtra() {
	    String str = getText().toString();
	    str = str.substring(0, str.length() - 1);
	    setText(str);
	    setSelection(getText().length());
	}

输入框宽度不固定

当要求输入框宽度需要动态调整时,实现就稍微复杂些。
这里有个细节需要注意下,当EditText的宽度不是设置固定的话,通过getLineCount()方法获取的行数是错误的!所以这里不能简单地通过getLineCount()来判断当前行数。

具体思路:
因为输入框宽度动态调整只有在1行的情况下才会发生,当多于1行时输入框宽度就是固定的了。所以这里的关键就是怎么不通过getLineCount()方法来区分1行和多行的情况。当大于1行时设置输入框宽度为最大宽度,这样getLineCount()就是正确的行数了。

如何不通过getLineCount()区分1行和多行的情况?
可以通过测量文本的宽度,当文本的宽度除以单行最大文本宽度大于等于1时说明行数大于1。具体代码如下:

	//计算此时输入框的宽度
	float width = mTextPaint.measureText(s.toString())+getPaddingLeft()+getPaddingRight();
	//计算此时应该显示几行
	int lineCountMeasured = (int) (width / mSingleMaxWidth) + 1;

当行数是1并且输入框宽度大于最小宽度时则需要手动调整输入框的宽度为当前宽度。这样做的目的是因为当文本多于1行时设置了输入框宽度为最大宽度不再是wrap_content,而当输入框从多行变成1行时继续删除文本则输入框的宽度需要自适应文本宽度调小,直到调整到最小宽度为止。

	if (lineCountMeasured == 1) {
	   //当只有1行时需要根据输入的内容动态调整EditText宽度
	   if (width > mSingleMinWidth) {
	       setWidth((int) width);
	   }
	}

当行数大于1时,需要设置输入框的宽度为最大宽度。这时候输入框宽度就是固定的了,通过getLineCount得到的行数就是正确的行数。

	if (lineCountMeasured > 1) {
	   //当大于1行时需要固定EditText的宽度,这样通过EditText.getLineCount()方法获取的行数才是正确的
	   setWidth((int) mSingleMaxWidth);
	}

当行数大于n行时删除多余的字符。

	int lineCount = getLineCount();
	if (lineCount > MAX_INPUT_LINES) {
	   //发现输入的内容大于最大行数,则删除多余的内容
	   deleteExtra();
	}

完整代码:

	@Override
	public void onTextChanged(CharSequence s, int start, int before, int count) {
		//计算此时输入框的宽度
		float width = mTextPaint.measureText(s.toString())+getPaddingLeft()+getPaddingRight();
		//计算此时应该显示几行
		int lineCountMeasured = (int) (width / mSingleMaxWidth) + 1;
		if (lineCountMeasured == 1) {
		   //当只有1行时需要根据输入的内容动态调整EditText宽度
		   if (width > mSingleMinWidth) {
		       setWidth((int) width);
		   }
		}
		if (lineCountMeasured > 1) {
		   //当大于1行时需要固定EditText的宽度,这样通过EditText.getLineCount()方法获取的行数才是正确的
		   setWidth((int) mSingleMaxWidth);
		}
		
		int lineCount = getLineCount();
		if (lineCount > DyLimitedLinesEditText.MAX_INPUT_LINES) {
		   //发现输入的内容大于最大行数,则删除多余的内容
		   deleteExtra();
		}
	}

代码地址

对于两种实现,我已经封装成自定义控件上传到github,地址如下:
实现1戳这里

实现2戳这里

如果觉得对你有帮助,麻烦点个赞支持下。

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值