Android+ テキスト検索・置換+ はテキストの検索・置換・元に戻すなどが可能で、基本的には .txt の検索・置換機能を PC 側で実現します。
最近のプロジェクトでは、PC のメモ帳に似た検索と置換機能を使用したため、実装時に比較的理解しやすいアルゴリズムのセットを自分で書きました。モバイル開発に基づいたテキスト検索および置換機能は、基本的に PC セグメントのメモ帳の検索および置換関連機能を実現します。基本的な機能には、検索、置換、すべて置換、元に戻す、前の項目、次の項目、カラー マーキング、位置の配置などが含まれます。
SpannableStringBuilder は、文字列を格納するために CharSequence クラスを実装します。SpannableStringBuilder には setSpan() 関数があり、保存された文字列にさまざまな形式や属性を追加し、下線、背景色、フォント色、クリック モニターの設定、ハイパーリンクの設定など、元の文字列をさまざまなスタイルで表示できます。主に使用されるのは背景色の設定です。興味のある学生は自分で調べることができます。
検索アルゴリズム
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;
}
}
具体的な方法を理解するには、デモをご覧ください: Android + テキストの検索と置換 + テキストの検索、置換、キャンセルなどが可能で、基本的に PC 側で .txt の検索と置換機能を実現 - Android ドキュメント リソース- CSDNライブラリ