Android+文本的查找和替换+可以对文本进行查找替换撤销等,基本实现了PC端.txt查找替换功能
最近项目用到了类似PC端记事本查找替换功能,于是自己就写了一套算法,实现起来还是比较容易理解的。基于移动开发的文本查找替换功能,基本实现了PC段记事本查找替换的相关功能。基本功能包括,查找、替换、全部替换、撤销、上一条、下一条、颜色标记和位置定位等功能。
SpannableStringBuilder实现了CharSequence类,用来存储字符串。SpannableStringBuilder有一个setSpan()函数,能给给存储的字符串添加各种各样的格式或者属性,,将原来的String以不同的样式显示出来,比如加上下划线、背景颜色、字体颜色、设置点击监听、设置超链接等。主要用到的就是设置背景颜色。有兴趣的同学可以自行了解一下。
查找算法
mBinding.tvSeek.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (TextUtils.isEmpty(mBinding.etName.getText().toString().trim())) {
showToast("输入查找内容");
return;
}
if (!mBinding.tvContent.getText().toString().contains(mBinding.etName.getText().toString())) {
showToast("查找内容不存在");
listFind = new ArrayList<>();
mBinding.tvNumber.setVisibility(View.INVISIBLE);
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(mBinding.tvContent.getText().toString());
BackgroundColorSpan colorSpan;
colorSpan = new BackgroundColorSpan(Color.parseColor("#ffffff"));
spannableStringBuilder.setSpan(colorSpan, 0, mBinding.tvContent.getText().toString().length() - 1, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
mBinding.tvContent.setText(spannableStringBuilder);
return;
}
findKey = mBinding.etName.getText().toString();
listReplace = new ArrayList<>();
mBinding.tvContent.getText().toString().contains(mBinding.etName.getText().toString());
getSubString(mBinding.tvContent.getText().toString(), findKey);
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(mBinding.tvContent.getText().toString());
if (listFind != null && listFind.size() != 0) {
for (int i = 0; i < listFind.size(); i++) {
BackgroundColorSpan colorSpan;
if (i == 0) {
colorSpan = new BackgroundColorSpan(Color.parseColor("#f50707"));
} else {
colorSpan = new BackgroundColorSpan(Color.parseColor("#AC00FF30"));
}
spannableStringBuilder.setSpan(colorSpan, listFind.get(i).getStart(), listFind.get(i).getEnd(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
}
mBinding.tvNumber.setVisibility(View.VISIBLE);
mBinding.tvNumber.setText("查找到" + listFind.size() + "条内容");
} else {
BackgroundColorSpan colorSpan;
colorSpan = new BackgroundColorSpan(Color.parseColor("#212832"));
spannableStringBuilder.setSpan(colorSpan, 0, mBinding.tvContent.getText().length() - 1, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
mBinding.tvNumber.setVisibility(View.INVISIBLE);
}
mBinding.tvContent.setText(spannableStringBuilder);
}
});
查找定位算法
mBinding.tvPrevious.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (listFind != null && listFind.size() != 0) {
if (select > 0) {
select = select - 1;
} else if (select == 0) {
select = listFind.size() - 1;
}
} else {
return;
}
next();
}
});
private void next() {
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(mBinding.tvContent.getText().toString());
if (listFind != null && listFind.size() != 0) {
for (int i = 0; i < listFind.size(); i++) {
BackgroundColorSpan colorSpan = new BackgroundColorSpan(Color.parseColor("#AC00FF30"));
spannableStringBuilder.setSpan(colorSpan, listFind.get(i).getStart(), listFind.get(i).getEnd(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
}
}
if (listReplace != null && listReplace.size() != 0) {
for (int i = 0; i < listReplace.size(); i++) {
BackgroundColorSpan colorSpan = new BackgroundColorSpan(Color.parseColor("#f5e107"));
spannableStringBuilder.setSpan(colorSpan, listReplace.get(i).getStart(), listReplace.get(i).getEnd(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
}
}
BackgroundColorSpan colorSpan = new BackgroundColorSpan(Color.parseColor("#f50707"));
spannableStringBuilder.setSpan(colorSpan, listFind.get(select).getStart(), listFind.get(select).getEnd(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
mBinding.tvContent.setText(spannableStringBuilder);
mBinding.tvContent.setSelection(listFind.get(select).getStart(), listFind.get(select).getEnd());
}
替换算法
mBinding.tvReplace.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (TextUtils.isEmpty(findKey)) {
showToast("输入查找内容");
return;
}
if (TextUtils.isEmpty(mBinding.etNames.getText().toString())) {
showToast("输入替换内容");
return;
}
replaceKey = mBinding.etNames.getText().toString();
if (listFind != null && listFind.size() != 0) {
if (select <= listFind.size() - 1) {
} else {
select = 0;
}
} else {
showToast("没找到要替换的内容");
return;
}
if (select < listFind.size()) {
} else {
showToast("没找到要替换的内容");
return;
}
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(mBinding.tvContent.getText().toString());
spannableStringBuilder.replace(listFind.get(select).getStart(), listFind.get(select).getEnd(), replaceKey);
FindBean findBean = new FindBean();
findBean.setStart(listFind.get(select).getStart());
findBean.setEnd(listFind.get(select).getStart() + replaceKey.length());
listReplace.add(findBean);
listFind.remove(select);
if (listFind != null && listFind.size() != 0) {
for (int i = 0; i < listFind.size(); i++) {
if (listFind.get(i).getStart() > findBean.getStart()) {
int sub1 = findBean.getEnd() - findBean.getStart();
int sub2 = listFind.get(i).getEnd() - listFind.get(i).getStart();
listFind.get(i).setStart(listFind.get(i).getStart() + sub1 - sub2);
listFind.get(i).setEnd(listFind.get(i).getEnd() + sub1 - sub2);
}
}
}
if (listReplace != null && listReplace.size() != 0) {
for (int i = 0; i < listReplace.size(); i++) {
if (listReplace.get(i).getStart() > findBean.getStart()) {
int sub1 = findBean.getEnd() - findBean.getStart();
listReplace.get(i).setStart(listReplace.get(i).getStart() + sub1 - findKey.length());
listReplace.get(i).setEnd(listReplace.get(i).getEnd() + sub1 - findKey.length());
}
}
}
for (int i = 0; i < listFind.size(); i++) {
BackgroundColorSpan colorSpan;
if (i == select) {
colorSpan = new BackgroundColorSpan(Color.parseColor("#f50707"));
} else {
colorSpan = new BackgroundColorSpan(Color.parseColor("#AC00FF30"));
}
spannableStringBuilder.setSpan(colorSpan, listFind.get(i).getStart(), listFind.get(i).getEnd(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
}
for (int i = 0; i < listReplace.size(); i++) {
BackgroundColorSpan colorSpan = new BackgroundColorSpan(Color.parseColor("#f5e107"));
spannableStringBuilder.setSpan(colorSpan, listReplace.get(i).getStart(), listReplace.get(i).getEnd(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
}
mBinding.tvContent.setText(spannableStringBuilder);
mBinding.tvContent.setSelection(listFind.get(select).getStart(), listFind.get(select).getEnd());
}
});
撤销算法
mBinding.tvUndo.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (listReplace != null && listReplace.size() != 0) {
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(mBinding.tvContent.getText().toString());
spannableStringBuilder.replace(listReplace.get(listReplace.size() - 1).getStart(), listReplace.get(listReplace.size() - 1).getEnd(), findKey);
FindBean findBean = new FindBean();
findBean.setStart(listReplace.get(listReplace.size() - 1).getStart());
findBean.setEnd(listReplace.get(listReplace.size() - 1).getStart() + findKey.length());
listFind.add(findBean);
Collections.sort(listFind, new Comparator<FindBean>() {
@Override
public int compare(FindBean o1, FindBean o2) {
int diff = o1.getStart() - o2.getStart();
if (diff > 0) {
return 1;
} else if (diff < 0) {
return -1;
}
return 0; //相等为0
}
});
select = listFind.indexOf(findBean);
listReplace.remove(listReplace.size() - 1);
if (listFind != null && listFind.size() != 0) {
for (int i = 0; i < listFind.size(); i++) {
if (listFind.get(i).getStart() > findBean.getStart()) {
int sub1 = findBean.getEnd() - findBean.getStart();
listFind.get(i).setStart(listFind.get(i).getStart() + sub1 - replaceKey.length());
listFind.get(i).setEnd(listFind.get(i).getEnd() + sub1 - replaceKey.length());
}
}
}
if (listReplace != null && listReplace.size() != 0) {
for (int i = 0; i < listReplace.size(); i++) {
if (listReplace.get(i).getStart() > findBean.getStart()) {
int sub1 = findBean.getEnd() - findBean.getStart();
int sub2 = listReplace.get(i).getEnd() - listReplace.get(i).getStart();
listReplace.get(i).setStart(listReplace.get(i).getStart() + sub1 - sub2);
listReplace.get(i).setEnd(listReplace.get(i).getEnd() + sub1 - sub2);
}
}
}
for (int i = 0; i < listFind.size(); i++) {
BackgroundColorSpan colorSpan = new BackgroundColorSpan(Color.parseColor("#AC00FF30"));
spannableStringBuilder.setSpan(colorSpan, listFind.get(i).getStart(), listFind.get(i).getEnd(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
}
for (int i = 0; i < listReplace.size(); i++) {
BackgroundColorSpan colorSpan = new BackgroundColorSpan(Color.parseColor("#f5e107"));
spannableStringBuilder.setSpan(colorSpan, listReplace.get(i).getStart(), listReplace.get(i).getEnd(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
}
mBinding.tvContent.setText(spannableStringBuilder);
mBinding.tvContent.setSelection(listFind.get(select).getStart(), listFind.get(select).getEnd());
} else {
showToast("撤销完毕");
}
}
});
记录下标位置对象
public class FindBean {
private int start;
private int end;
public int getStart() {
return start;
}
public void setStart(int start) {
this.start = start;
}
public int getEnd() {
return end;
}
public void setEnd(int end) {
this.end = end;
}
}
了解具体做法可以产看demo:Android+文本的查找和替换+可以对文本进行查找替换撤销等,基本实现了PC端.txt查找替换功能-Android文档类资源-CSDN文库