实现edittext搜索,Recyclerview+关键字动态匹配筛选变色效果。
edittext——recycleview.jpg
先修改search_page.xml,加一个RecyclerView。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/shape_edittext"
android:layout_marginTop="20dp"
android:layout_marginLeft="10dp"
android:orientation="horizontal">
<EditText
android:id="@+id/searchEd"
android:drawableLeft="@drawable/search_gray"
android:background="@null"
android:layout_width="270dp"
android:layout_height="wrap_content"
/>
<ImageView
android:id="@+id/speak"
android:src="@drawable/audio"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
<TextView
android:text="搜索"
android:textColor="@android:color/holo_blue_dark"
android:layout_marginTop="23dp"
android:paddingLeft="5dp"
android:textSize="17dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/searchRecycle"
android:layout_width="wrap_content"
android:layout_height="match_parent"/>
</LinearLayout>
设置edittext输入监听:
searchEd.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
getSearchNet(s.toString());
searchString = s.toString();
}
@Override
public void afterTextChanged(Editable s) {
}
});
return view;
}
将输入的关键字请求搜索内容。
public void getSearchNet(String str){
presenter.getSearch(searchUrl+str);
}
public void getSearch(String str) {
Log.v("eee", "333==");
Observable<SearchModel> observable = mModel.getSearch(str);
observable.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<SearchModel>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(SearchModel model) {
Log.v("eee", "222=="+model.getData().get(0).getWord());
searchModel = model;
}
@Override
public void onError(Throwable e) {
Log.v("abbb", "222=="+e);
}
@Override
public void onComplete() {
Log.v("eee", "333==");
mView.getSearchModel(searchModel);
}
});
}
@Override
public Observable<SearchModel> getSearch(String searchStr) {
Observable<SearchModel> observable = RetrofitHelper.getInstance().getServer().getSearch(searchStr);
}
@Headers("Content-Type: application/json")
@GET
Observable<SearchModel> getSearch(@Url String url);
请求的url是https://m.ctrip.com/restapi/h5api/searchapp/search?source=mobileweb&action=autocomplete&contentType=json&keyword=
加上输入的关键字。可以随便填个关键字,用工具生成SearchModel。
请求结果传回SearchPageActivity。
@Override
public void getSearchModel(SearchModel searchModel) {
searchAdapter.getData(searchModel,searchString);
}
创建SearchAdapter,以及recycleview每个item的search_item.xml。
public class SearchAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
List<SearchModel.Data> datas = new ArrayList();
String keyWord;
Activity context;
String[] TYPES = {
"channelgroup",
"gs",
"plane",
"train",
"cruise",
"district",
"food",
"hotel",
"huodong",
"shop",
"sight",
"ticket",
"travelgroup"
};
int[] DrawableResTYPES = {
R.drawable.type_channelgroup,
R.drawable.type_channelgs,
R.drawable.type_channelplane,
R.drawable.type_channeltrain,
R.drawable.type_cruise,
R.drawable.type_district,
R.drawable.type_food,
R.drawable.type_hotel,
R.drawable.type_huodong,
R.drawable.type_shop,
R.drawable.type_sight,
R.drawable.type_ticket,
R.drawable.type_travelgroup,
};
public SearchAdapter(Activity context) {
this.context = context;
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new SearchItemViewHolder(LayoutInflater.from(parent.getContext())
.inflate(R.layout.search_item, parent, false));
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
if (holder instanceof SearchItemViewHolder) {
((SearchItemViewHolder) holder).searchImage.setImageResource(imageType(datas.get(position).getType()));
((SearchItemViewHolder) holder).searchItem.setText(
KeyWordUtil.matcherSearchTitle(Color.GREEN, datas.get(position).getWord(), keyWord));
Log.v("pe", "==" + datas.get(position).getPrice());
if (datas.get(position).getPrice() == null) {
((SearchItemViewHolder) holder).searchSubItem.setVisibility(View.GONE);
} else {
((SearchItemViewHolder) holder).searchSubItem.setText("¥" + datas.get(position).getPrice());
}
final String webViewUrl = datas.get(position).getUrl();
((SearchItemViewHolder) holder).searchLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
intoWebView(webViewUrl);
}
});
}
}
public int imageType(String type) {
if (type == null) {
return R.drawable.type_channeltrain;
}
int path = 0;
for (int a = 0; a < TYPES.length; a++) {
if (type.contains(TYPES[a])) {
path = a;
}
}
return DrawableResTYPES[path];
}
public void intoWebView(String url) {
Intent startIntent = new Intent(context, WebViewActivity.class);
startIntent.putExtra(ConstantsUtil.LOCAL_URL, url);
context.startActivity(startIntent);
}
@Override
public int getItemCount() {
return datas.size();
}
public class SearchItemViewHolder extends RecyclerView.ViewHolder {
LinearLayout searchLayout;
ImageView searchImage;
TextView searchItem;
TextView searchSubItem;
public SearchItemViewHolder(@NonNull View itemView) {
super(itemView);
searchLayout = itemView.findViewById(R.id.search_item_layout);
searchImage = itemView.findViewById(R.id.search_image);
searchItem = itemView.findViewById(R.id.search_text);
searchSubItem = itemView.findViewById(R.id.search_sub_text);
}
}
public void getData(SearchModel searchModel, String searchWord) {
datas = searchModel.getData();
keyWord = searchWord;
notifyDataSetChanged();
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/search_item_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp"
android:orientation="horizontal">
<ImageView
android:layout_gravity="center_vertical"
android:id="@+id/search_image"
android:padding="1dp"
android:layout_width="26dp"
android:layout_height="26dp" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/search_text"
android:layout_width="300dp"
android:layout_height="wrap_content"
android:maxLines="1"
android:ellipsize="end"
android:text="ff"
android:textSize="16dp" />
<TextView
android:id="@+id/search_sub_text"
android:layout_width="300dp"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:maxLines="1"
android:textColor="#FFA500"
android:ellipsize="end"
android:text="ff"
android:textSize="16dp" />
</LinearLayout>
</LinearLayout>
需要注意的就是SearchAdapter里面,将搜索的关键字高亮了,具体操作是:
创建一个工具类KeyWordUtil:
/**
* 文字变色工具类
*/
public class KeyWordUtil {
/**
* 关键字高亮变色
*
* @param color 变化的色值
* @param text 文字
* @param keyword 文字中的关键字
* @return 结果SpannableString
*/
public static SpannableString matcherSearchTitle(int color, String text, String keyword) {
Log.v("gg","text=="+text+"=="+keyword);
SpannableString s = new SpannableString(text);
keyword = escapeExprSpecialWord(keyword);
text = escapeExprSpecialWord(text);
if (text.contains(keyword) && !TextUtils.isEmpty(keyword)) {
try {
Pattern p = Pattern.compile(keyword);
Matcher m = p.matcher(s);
while (m.find()) {
Log.v("gg","2222");
int start = m.start();
int end = m.end();
s.setSpan(new ForegroundColorSpan(color), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
} catch (Exception e) {
}
}
return s;
}
/**
* 转义正则特殊字符 ($()*+.[]?\^{},|)
*
* @param keyword
* @return keyword
*/
public static String escapeExprSpecialWord(String keyword) {
if (!TextUtils.isEmpty(keyword)) {
String[] fbsArr = {"\\", "$", "(", ")", "*", "+", ".", "[", "]", "?", "^", "{", "}", "|"};
for (String key : fbsArr) {
if (keyword.contains(key)) {
keyword = keyword.replace(key, "\\" + key);
}
}
}
return keyword;
}
}
将整个string和关键字,以及颜色传过去就好。
KeyWordUtil.matcherSearchTitle(Color.GREEN, datas.get(position).getWord(), keyWord))
注意这个颜色,需要用Color.xx,用R.color.xx的无效。
具体代码如下:
https://github.com/doudousang/edittext_recyclerview.git
参考代码:
Android搜索关键字高亮显示
SpannableString详细解析
网友评论