300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > Android开发:SearchView与搜索

Android开发:SearchView与搜索

时间:2023-02-07 15:05:09

相关推荐

Android开发:SearchView与搜索

搜索控件SearchView介绍

我们在Android开发中,需要实现搜索功能,例如文章搜索、城市地点搜索和字典搜索等等,对此实现搜索功能可以使用SearchView,它是Android的一个控件,继承自LinearLayout。

SearchView的继承关系

类似于EditText,其能接收用户在搜索框输入的查询,通过适当配置可以将查询交给对应搜索Activity并返回相应结果,效果如下:

城市地点搜索

一般情况下就是SearchView和ListView(或是RecyclerView)配合使用,前者接收用户的查询,后者用于返回显示的查询结果。

SearchView的XML属性

SearchView具备xml属性无非就这五种,在设计布局时可以自己选择相应的属性进行设置。

若是使用SearchView进行搜索,则通常情况下将inputType属性设置成 "textFilter" 进行文本过滤,属性queryHint中输入想提示用户的内容,代码如下:

​<androidx.appcompat.widget.SearchViewandroid:id="@+id/searchView"android:layout_width="wrap_content"android:layout_height="wrap_content"app:iconifiedByDefault="false"android:inputType="textFilter"app:defaultQueryHint="请输入搜索内容" />

为了适配其他Android版本机型,需要使用命名空间app,在布局中引入xmlns:app="/apk/res-auto" 这段代码。

实现可搜索的Activity

只有SearchView的话可不能实现搜索功能,在用户眼里就和EditView无异。这时就要进入激动人心的java代码书写,其中步骤如下:

绑定SearchView和ListView并设置二者的属性实现ListView的适配器Adapter和其中的过滤规则在Activity中重写搜索改变方法设置ListView各项的监听器实现后续逻辑

其中第一步过于简单可以略过,从第二步开始其实就是ListView的相关内容,即数据List和Adapter适配

适配器Adatper和过滤规则Filter

关于Adatper的内容不多赘述,其中值得注意的是,在写ListView的Adapter时不光继承BaseAdapter,同时需要实现Filterable,即public class SearchAdapter extends BaseAdapter implements Filterable {...} 来创建我们的过滤规则,而且对于绑定的数据,List需要两份,一份用于数据和ListView的绑定,另一份用于展示过滤后的数据,演示的java代码如下:

​public class SearchAdapter extends BaseAdapter implements Filterable {private Context context;private List<String> searchList;private List<String> backSearchList;public SearchAdapter(Context context, List<String> list) {this.context = context;this.SearchList = list;this.backSearchList = list;}//...}

接着便要着手我们的自定义过滤规则了,通过继承Filter类,重写performFiltering方法定义规则如下:

​/*** 定义过滤器的类来定义过滤规则*/class MyFilter extends Filter {//在performFiltering(CharSequence charSequence)这个方法中定义过滤规则@Overrideprotected FilterResults performFiltering(CharSequence constraint) {List<String> list = new ArrayList<>();if (!TextUtils.isEmpty(constraint)) {//当过滤的关键字不为空的时候,把符合条件的数据对象添加到集合中for (String search : searchList) {if (search.contains(constraint)) {//要匹配的item中的viewlist.add(search);}}}FilterResults results = new FilterResults();results.values = list;results.count = list.size();return results;}

其中我们先定义了一个list来暂存过滤后的结果数据列表,通过判断用户输入的constraint内容后,如果不是空则遍历原先定义的search,并把包含constraint的内容保存到list中,最后返回包含list数据和大小的result过滤结果。

然后重写publishResults方法让适配器更新搜索界面。

//在publishResults方法中让适配器更新界面@Overrideprotected void publishResults(CharSequence constraint, FilterResults results) {backSearchList = (List<String>) results.values;if (results.count > 0) {notifyDataSetChanged(); //通知数据发生了改变} else {notifyDataSetInvalidated(); //通知数据失效}}

在代码中我们将先前返回的results的内容保存至另一份backSearchList中,并通知数据改变与否。

然后别忘了在SearchAdapter类中声明我们的自定义myFilter,同时需要重写getFilter方法。

下面是完整的SearchAdatper类的代码:

public class SearchAdapter extends BaseAdapter implements Filterable {private Context context;private List<CitySearch> searchList;private List<CitySearch> backSearchList;MyFilter mFilter;//Search为自定义的类public SearchAdapter(Context context, List<Search> searchList) {this.context = context;this.searchList = searchList;this.backSearchList = searchList;}public SearchAdapter() {}//getCount和getItem都要返回backSearchList的数据@Overridepublic int getCount() {return backSearchList.size();}@Overridepublic Object getItem(int position) {return backSearchList.get(position);}@Overridepublic long getItemId(int position) {return position;}class ViewHolder {//定义控件}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {ViewHolder holder = null;if (convertView == null) {convertView = View.inflate(context, R.layout.activity_search_item, null);holder = new ViewHolder();//holder定义的控件绑定布局控件convertView.setTag(holder);} else {holder = (ViewHolder) convertView.getTag();}//控件内容和list数据绑定return convertView;}@Overridepublic Filter getFilter() {if (mFilter == null) {mFilter = new MyFilter();}return mFilter;}/*** 定义过滤器的类来定义过滤规则*/class MyFilter extends Filter {//在performFiltering(CharSequence charSequence)这个方法中定义过滤规则@Overrideprotected FilterResults performFiltering(CharSequence constraint) {List<Search> list = new ArrayList<>();if (!TextUtils.isEmpty(constraint)) {//当过滤的关键字不为空的时候,把符合条件的数据对象添加到集合中for (Search search : citySearchList) {if (search.getAreaName().contains(constraint)) {//要匹配的item中的viewlist.add(search);}}}//results保存过滤的数据FilterResults results = new FilterResults();results.values = list;results.count = list.size();return results;}//在publishResults方法中让适配器更新界面@Overrideprotected void publishResults(CharSequence constraint, FilterResults results) {backSearchList = (List<Search>) results.values;if (results.count > 0) {notifyDataSetChanged(); //通知数据发生了改变} else {notifyDataSetInvalidated(); //通知数据失效}}}}

需要注意的是,在重写getCount和getItem要返回的是backSearchList的数据,因为最后为用户展示的是过滤后的结果,这些结果是与backSearchList数据对应的。

在活动Activity中重写搜索方法

上面一口气说了这么多,接下来就简单许多了,在我们的搜索Activity中只需重写onQueryTextChange和onQueryTextSubmit两个方法,前者在用户输入字符时激发,后者则是单击搜索按钮时激发。

@Override public boolean onQueryTextChange(String newText) {//如果newText是长度为0的字符串if (TextUtils.isEmpty(newText)) {//清除ListView的过滤searchListView.clearTextFilter();searchAdapter.getFilter().filter("");} else {//使用用户输入的内容对ListView的列表项进行过滤//searchListView.setFilterText(newText);searchAdapter.getFilter().filter(newText);}return true;}@Overridepublic boolean onQueryTextSubmit(String query) {return true;}

在其中我们不难发现,当搜索框中没有输入时,先使用clearTextFilter清除原本的过滤,同时设置filter为空,这样不显示没有过滤的全部数据,当然如果想显示所有数据那就删除这句代码。如果搜索框有内容时就将newText设置过滤,此时ListView就会显示包含newText搜索内容的数据。然后在Activity中添加

searchView.setOnQueryTextListener(this);

这句代码以设置SearchView的监听器

完成你的后续逻辑

你觉得仅是这样就结束了吗,这个时候只是完成了搜索和过滤功能,用户只能进行搜索,如果用户想搜索后点击查看,例如百度搜索跳转界面。这个时候你还需要添加你自己的后续逻辑,如ListView中设置监听器。

searchListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position, long id) {//search获取点击的itemSearch search = (Search) parent.getAdapter().getItem(position);//后续逻辑例如根据search内容跳转}});

中间的内容就根据自己的代码进行修改,例如使用intent跳转。

后记

这篇文章是在本人开发天气App所遇到的技术问题中得到的经验和总结,若是文章中出现的错误还望批评指正,另附上参考链接和天气App的GitHub地址:

创建搜索界面 | Android 开发者 | Android Developers ()

SearchView | Android Developers ()

Gilbert2510/WindowWeather ()

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。