当前位置:网站首页>使用InputFilter限制EditText时踩坑及解决方案
使用InputFilter限制EditText时踩坑及解决方案
2022-07-03 03:11:00 【超努力的金蟾菇】
当我们想做EditText字符上的一些限制时,我们通常会用到InputFilter,通过重写里面的filter方法以做到限制长度的输入等,但是可能有心的同学会发现,在一些特定的情况下可能会发生字符取代覆盖的情况——比如我们用到特殊的输入法
//InputFilter接口,需要重写filter方法
public interface InputFilter
{
/** * @param source 输入的文字 * @param start 输入-0,删除-0 * @param end 输入-source文字的长度,删除-0 * @param dest 原先显示的内容 * @param dstart 输入-原光标位置,删除-光标删除结束位置 * @param dend 输入-原光标位置,删除-光标删除开始位置 * @return */
//主要重写这个方法
public CharSequence filter(CharSequence source, int start, int end,
Spanned dest, int dstart, int dend);
/** * This filter will capitalize all the lower case letters that are added * through edits. */
//接口内的静态内部类,,,输入小写转换成大写
public static class AllCaps implements InputFilter {
public CharSequence filter(CharSequence source, int start, int end,
Spanned dest, int dstart, int dend) {
for (int i = start; i < end; i++) {
if (Character.isLowerCase(source.charAt(i))) {
char[] v = new char[end - start];
TextUtils.getChars(source, start, end, v, 0);
String s = new String(v).toUpperCase();
if (source instanceof Spanned) {
SpannableString sp = new SpannableString(s);
TextUtils.copySpansFrom((Spanned) source,
start, end, null, sp, 0);
return sp;
} else {
return s;
}
}
}
return null; // keep original
}
}
/** * This filter will constrain edits not to make the length of the text * greater than the specified length. */
// 长度过滤器,限制输入的长度
public static class LengthFilter implements InputFilter {
private final int mMax;
public LengthFilter(int max) {
mMax = max;
}
public CharSequence filter(CharSequence source, int start, int end, Spanned dest,
int dstart, int dend) {
int keep = mMax - (dest.length() - (dend - dstart));
if (keep <= 0) {
return ""; //主要问题出在这里,虽然inputfilter可以做输入过程中的长度限制,但是却不能对光标做任何的修改
} else if (keep >= end - start) {
return null; // keep original
} else {
keep += start;
if (Character.isHighSurrogate(source.charAt(keep - 1))) {
--keep;
if (keep == start) {
return "";
}
}
return source.subSequence(start, keep);
}
}
/** * @return the maximum length enforced by this input filter */
public int getMax() {
return mMax;
}
}
}
遇到这种与输入法相关的情况,我们就可以尝试另一种更灵活使用也更广泛的方法——Textwatcher,这个方法可以在输入时获取光标位置操作,更可以直接在输入时做出灵活的限制。具体操作可以参考下面一位大佬写的类。
package com.example.edittext;
import android.content.Context;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.widget.EditText;
import android.widget.Toast;
/** * 自定义MyTextWatcher类实现TextWatcher接口,并重写相关方法 * * @author 邹奇 * */
public class MyTextWatcher implements TextWatcher {
private int limit;// 字符个数限制
private EditText text;// 编辑框控件
private Context context;// 上下文对象
int cursor = 0;// 用来记录输入字符的时候光标的位置
int before_length;// 用来标注输入某一内容之前的编辑框中的内容的长度
public MyTextWatcher(EditText text, int limit,
Context context) {
this.limit = limit;
this.text = text;
this.context = context;
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
before_length = s.length();
}
/** * s 编辑框中全部的内容 、start 编辑框中光标所在的位置(从0开始计算)、count 从手机的输入法中输入的字符个数 */
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
cursor = start;
// Log.e("此时光标的位置为", cursor + "");
}
@Override
public void afterTextChanged(Editable s) {
// 这里可以知道你已经输入的字数,大家可以自己根据需求来自定义文本控件实时的显示已经输入的字符个数
Log.e("此时你已经输入了", "" + s.length());
int after_length = s.length();// 输入内容后编辑框所有内容的总长度
// 如果字符添加后超过了限制的长度,那么就移除后面添加的那一部分,这个很关键
if (after_length > limit) {
// 比限制的最大数超出了多少字
int d_value = after_length - limit;
// 这时候从手机输入的字的个数
int d_num = after_length - before_length;
int st = cursor + (d_num - d_value);// 需要删除的超出部分的开始位置
int en = cursor + d_num;// 需要删除的超出部分的末尾位置
// 调用delete()方法将编辑框中超出部分的内容去掉
Editable s_new = s.delete(st, en);
// 给编辑框重新设置文本
text.setText(s_new.toString());
// 设置光标最后显示的位置为超出部分的开始位置,优化体验
text.setSelection(st);
// 弹出信息提示已超出字数限制
Toast.makeText(context, "已超出最大字数限制", Toast.LENGTH_SHORT).show();
}
}
}
最后附上两位大佬的代码链接(狗头保命
边栏推荐
- C语言初阶-指针详解-庖丁解牛篇
- 后管中编辑与预览获取表单的值写法
- Add some hard dishes to the interview: how to improve throughput and timeliness in delayed task scenarios!
- Destroy the session and empty the specified attributes
- [combinatorics] Application of exponential generating function (multiple set arrangement problem | different balls in different boxes | derivation of exponential generating function of odd / even sequ
- 解决高并发下System.currentTimeMillis卡顿
- MySql实战45讲【事务隔离】
- 别再用 System.currentTimeMillis() 统计耗时了,太 Low,StopWatch 好用到爆!
- 用docker 連接mysql的過程
- Joking about Domain Driven Design (III) -- Dilemma
猜你喜欢
Spark on yarn资源优化思路笔记
vfork执行时出现Segmentation fault
Idea set method call ignore case
Do you really understand relays?
从C到Capable-----利用指针作为函数参数求字符串是否为回文字符
Nasvit: neural architecture search of efficient visual converter with gradient conflict perception hypernetwork training
45 lectures on MySQL [index]
PAT乙级“1104 天长地久”DFS优化思路
Le processus de connexion mysql avec docker
Idea format code idea set shortcut key format code
随机推荐
Three.js本地环境搭建
别再用 System.currentTimeMillis() 统计耗时了,太 Low,StopWatch 好用到爆!
vfork执行时出现Segmentation fault
Force deduction ----- the minimum path cost in the grid
Vs 2019 configure tensorrt to generate engine
VS code配置虚拟环境
The idea setting code is in UTF-8 idea Properties configuration file Chinese garbled
分布式事务
[shutter] monitor the transparency gradient of the scrolling action control component (remove the blank of the top status bar | frame layout component | transparency component | monitor the scrolling
Update and return document in mongodb - update and return document in mongodb
js根据树结构查找某个节点的下面的所有父节点或者子节点
Can netstat still play like this?
The solution of "the required function is not supported" in win10 remote desktop connection is to modify the Registry [easy to understand]
What does it mean when lambda is not entered?
I2C 子系统(一):I2C spec
Andwhere multiple or query ORM conditions in yii2
Vs 2019 configuration du moteur de génération de tensorrt
Sqlserver row to column pivot
MySQL practice 45 [global lock and table lock]
The process of connecting MySQL with docker