,当然还有许多逻辑可能需要你在处理处理,这个只能算一个简单版最近在写一个功能,类似于微博的话题,#xx 这种。我们在输入框中输入文字,如果输入了#,那就开始搜索后台服务器。然后给你展示一堆热门的话题 ,你点击,选中,然后高亮显示 或者你自己输入,最后以空格啊特殊符号啊,结束,这个规则可以自己定制。需求来了,先简单分析一波 吧:
1.正则规则,这个简单,根据你们制定的,我这规则是,#号开头,非汉字或者字母数字结束,最多3个话题
所以正则是:"(#(#{0}?[\\u4e00-\\u9fa5A-Za-z0-9]+))"
然后非法限定字符是([\\u4e00-\\u9fa5A-Za-z0-9]+)
2.判断当前输入的是啥,所以肯定得在TextWatch里做文章
onTextChanged 中参数的意思,你得先去了解一波,,before=0 是你往里面加字符串,count=0,是删除字符串,然后对应着判断逻辑就好
3。改变颜色 这里的水有点深,可能是我太菜了。
第一个版本:参考 https://github.com/limedroid/TagEditText,
afterTextChanged里的写法,改吧改吧,能用,但是会有问题,在一些机器的一些输入法中,你输入一个,然后给你来个智能提示,你点了那个提示,就出问题了,或者是各种下划线,不能操作,
然后就是搜啊搜的
第二个参考:https://www.jianshu.com/p/d0dbb3445cc1
然后还有第三,第四,大体上都是 在after里,先removewatch,再加watch,或者用html.fromHtml来改颜色,但是都有问题。
最终版来自于 https://stackoverflow.com/questions/42786493/syntax-highlighting-on-android-edittext-using-span
就不废话了,,直接上代码吧,当然了这个只能算一个简单版,还有许多逻辑需要你自己处理,我项目中后续也改了不少,这里只是提供个思路,重点是如何在edittext中输入然后实时改颜色或者其他span
public class TagEditText extends AppCompatEditText {
public String prefixTag = "#";
private String endTag = "#";
private String tagRegex = DEF_REGEX;
public static final String DEF_REGEX = "(#(#{0}?[\\u4e00-\\u9fa5A-Za-z0-9]+))";//字符串中只允许1个#
public static String ILLEGAL_REGEX = "([\\u4e00-\\u9fa5A-Za-z0-9]+)";
private int tagColor = Color.parseColor("#1B97AA");
private boolean isSearch = false;
List<String> tagList = new ArrayList<>();
int lastSelction = 0;
public void setSearchState(boolean isSearch) {
this.isSearch = isSearch;
}
public TagEditText(Context context) {
super(context);
initView();
}
public TagEditText(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}
public TagEditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView();
}
private void initView() {
addTextChangedListener(new TextWatcher() {
private String mBeafore = "";
private int deletCount = 0;
private int deleteStart = 0;
private int selection = 0;
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
mBeafore = s.toString();
deletCount = count;
deleteStart = start;
selection=getSelectionEnd();
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
selection=getSelectionEnd();
if (before == 0) {
//添加
if (s.subSequence(start, start + count).toString().equals(prefixTag)) {
Timber.d("---开始搜索");
if (getTagList().size() >= 3) {
isSearch = false;
if (searchListener != null) {
searchListener.unSearch();
}
} else {
isSearch = true;
if (searchListener != null) {
searchListener.search("");
}
}
} else if (s.subSequence(start, start + count).toString().equals(" ") || s.subSequence(start, start + count).toString().equals("\r\n") || s.subSequence(start, start + count).toString().equals("\n") || !check(s.subSequence(start, start + count).toString())) {
//空格搜索结束
isSearch = false;
if (searchListener != null) {
searchListener.unSearch();
}
} else {
if (isSearch) {
String str = s.toString().substring(s.toString().lastIndexOf(prefixTag) + 1);
Timber.d("---搜索%s", str);
if (searchListener != null) {
searchListener.search(str);
}
} else {
Timber.d("---不搜索");
if (searchListener != null) {
searchListener.unSearch();
}
}
}
} else if (count == 0) {
Timber.d("----delete");
//删除
if (getTagList().size() > 3) {
isSearch = false;
if (searchListener != null) {
searchListener.unSearch();
}
return;
}
String str = s.toString().substring(s.toString().lastIndexOf(prefixTag) + 1, mBeafore.length() - before);
String deleteStr = mBeafore.substring(deleteStart, deleteStart + deletCount);
if (isSearch) {
if (prefixTag.equals(deleteStr)) {
//删除的是#
isSearch = false;
Timber.d("---不搜索%s", str);
if (searchListener != null) {
searchListener.unSearch();
}
} else {
Timber.d("---搜索%s", str);
if (searchListener != null) {
searchListener.search(str);
}
}
} else {
if (s.toString().lastIndexOf(prefixTag) < 0) {
Timber.d("---不搜索%s", str);
isSearch = false;
if (searchListener != null) {
searchListener.unSearch();
}
return;
}
String tempStr = s.toString().substring(s.toString().lastIndexOf(prefixTag), mBeafore.length() - before);
Timber.d("----tempStr=%s", tempStr);
Pattern pattern = Pattern.compile(tagRegex);
Matcher matcher = pattern.matcher(tempStr);
String match = "";
if (matcher.find()) {
match = matcher.group(1);
if (match.equals(tempStr)) {
Timber.d("---搜索%s", str);
isSearch = true;
if (searchListener != null) {
searchListener.search(str);
}
}
} else if (tempStr.equals(prefixTag)) {
Timber.d("---搜索%s", str);
isSearch = true;
if (searchListener != null) {
searchListener.search(str);
}
} else {
Timber.d("---不搜索%s", str);
isSearch = false;
if (searchListener != null) {
searchListener.unSearch();
}
}
}
}
}
@Override
public void afterTextChanged(Editable text) {
if (TextUtils.isEmpty(text)) {
isSearch = false;
searchListener.unSearch();
return;
}
removeSpans(text, ForegroundColorSpan.class);
String textStr = text.toString();
if (TextUtils.isEmpty(tagRegex)) tagRegex = DEF_REGEX;
Pattern pattern = Pattern.compile(tagRegex);
Matcher matcher = pattern.matcher(textStr);
tagList.clear();
while (matcher.find()) {
if (tagList.size() < 3) {
tagList.add(matcher.group(1));
text.setSpan(new ForegroundColorSpan(tagColor),
matcher.start(),
matcher.end(),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
if (selection==0){
Selection.setSelection(text,text.length());
}else {
Selection.setSelection(text,selection);
}
}
});
}
void removeSpans(Editable e, Class<? extends CharacterStyle> type) {
CharacterStyle[] spans = e.getSpans(0, e.length(), type);
for (CharacterStyle span : spans) {
e.removeSpan(span);
}
}
@Override
protected void onSelectionChanged(int selStart, int selEnd) {
super.onSelectionChanged(selStart, selEnd);
}
/**
* 设置tag
*
* @param prefixTag
* @param endTag
*/
public TagEditText tag(String prefixTag, String endTag) {
if (TextUtils.isEmpty(prefixTag) || TextUtils.isEmpty(endTag)) return this;
this.prefixTag = prefixTag;
this.endTag = endTag;
tagRegex = new StringBuilder("(")
.append(prefixTag)
.append(".+?")
.append(endTag)
.append(")")
.toString();
return this;
}
/**
* 设置标签颜色
*
* @param tagColor
* @return
*/
public TagEditText tagColor(int tagColor) {
this.tagColor = tagColor;
return this;
}
/**
* 追加文本
*
* @param text
*/
public void appendText(String text) {
if (TextUtils.isEmpty(text)) return;
SpannableStringBuilder builder = new SpannableStringBuilder(getText());
builder.append(text);
setText(builder);
setSelection(getText().toString().length());
}
/**
* 删除文本[删除最后匹配]
*
* @param text
*/
public void removeText(String text) {
if (TextUtils.isEmpty(text)) return;
SpannableStringBuilder builder = new SpannableStringBuilder(getText());
int pos = text.toString().indexOf(text);
if (pos > -1) {
try {
builder = builder.delete(pos, pos + text.length());
setText(builder);
} catch (Exception e) {
}
}
}
/**
* 获取标签集合
*
* @return
*/
public List<String> getTagList() {
ArrayList<String> list = new ArrayList<>();
for (int i = 0; i < tagList.size(); i++) {
list.add(tagList.get(i).replace(prefixTag, ""));
}
return list;
// Pattern pattern = Pattern.compile(tagRegex);
// Matcher matcher = pattern.matcher(getText());
//
// Set<String> picSet = new HashSet<>();
// ArrayList<String> tagList = new ArrayList<>();
//
// while (matcher.find()) {
// picSet.add(matcher.group(1).replace(prefixTag, "").replace(endTag, ""));
// }
//
// tagList.clear();
// tagList.addAll(picSet); //去重
// return tagList;
}
public interface OnSearchListener {
void search(String text);
void unSearch();
}
public OnSearchListener searchListener;
public void setOnSearchListener(OnSearchListener searchListener) {
this.searchListener = searchListener;
}
public boolean check(String text) {
Pattern pattern = Pattern.compile(ILLEGAL_REGEX);
Matcher matcher = pattern.matcher(text);
while (matcher.find()) {
return true;
}
return false;
}
}
网友评论