今天,我们将研究Android SearchView小部件,并开发一个根据查询的文本过滤ListView的应用程序。我们将使用数据绑定来连接活动和适配器中的布局。如果您还没有读过有关数据绑定的内容,请首先参考this教程以更好地理解。
Android搜索视图
Android允许我们通过在工具栏/ActionBar中显示SearchView小部件或将其插入到布局中来使用应用程序中的搜索功能。Android SearchView小部件从Android 3.0开始可用。SearchView在XML布局中定义,如下所示。
1<android.support.v7.widget.SearchView
2 android:id="@+id/search"
3 android:layout_width="match_parent"
4 android:layout_height="wrap_content" />
在Android中有许多搜索形式,例如语音搜索,建议等。在本教程中,我们将使用SearchView. OnQueryTextView
和Filterable
接口。Filterable接口过滤ListView上的查询文本并显示结果ListView行。OnQueryText
接口可以检测两个事件。
当用户在文本字段中输入每个字符时,会调用onQueryTextChange
2.按下搜索触发onQueryTextSubmit
Android SearchView示例
下图显示了最终的Android SearchView示例项目。该项目由一个Activity和一个Listview适配器组成。
Android SearchView示例代码
Active_main.xml如下所示。它由顶部带有SearchView的ListView组成。active_main.xml
1<?xml version="1.0" encoding="utf-8"?>
2<layout xmlns:android="https://schemas.android.com/apk/res/android">
3
4 <RelativeLayout
5 android:layout_width="fill_parent"
6 android:layout_height="wrap_content"
7 android:orientation="horizontal">
8
9 <android.support.v7.widget.SearchView
10 android:id="@+id/search"
11 android:layout_width="match_parent"
12 android:layout_height="wrap_content"
13 android:clickable="true" />
14
15 <ListView
16 android:id="@+id/list_view"
17 android:layout_width="fill_parent"
18 android:layout_height="wrap_content"
19 android:layout_alignParentLeft="true"
20 android:layout_alignParentStart="true"
21 android:layout_below="@+id/search" />
22
23 </RelativeLayout>
24
25</layout>
下面给出了MainActivity.java。
1package com.journaldev.searchview;
2
3import android.databinding.DataBindingUtil;
4import android.support.v7.app.AppCompatActivity;
5import android.os.Bundle;
6import android.support.v7.widget.SearchView;
7
8import com.journaldev.searchview.databinding.ActivityMainBinding;
9
10import java.util.ArrayList;
11import java.util.List;
12
13public class MainActivity extends AppCompatActivity {
14
15 ActivityMainBinding activityMainBinding;
16 ListAdapter adapter;
17
18 List<String> arrayList= new ArrayList<>();
19
20 @Override
21 protected void onCreate(Bundle savedInstanceState) {
22 super.onCreate(savedInstanceState);
23 activityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
24
25 arrayList.add("January");
26 arrayList.add("February");
27 arrayList.add("March");
28 arrayList.add("April");
29 arrayList.add("May");
30 arrayList.add("June");
31 arrayList.add("July");
32 arrayList.add("August");
33 arrayList.add("September");
34 arrayList.add("October");
35 arrayList.add("November");
36 arrayList.add("December");
37
38 adapter= new ListAdapter(arrayList);
39 activityMainBinding.listView.setAdapter(adapter);
40
41 activityMainBinding.search.setActivated(true);
42 activityMainBinding.search.setQueryHint("Type your keyword here");
43 activityMainBinding.search.onActionViewExpanded();
44 activityMainBinding.search.setIconified(false);
45 activityMainBinding.search.clearFocus();
46
47 activityMainBinding.search.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
48 @Override
49 public boolean onQueryTextSubmit(String query) {
50 return false;
51 }
52
53 @Override
54 public boolean onQueryTextChange(String newText) {
55
56 adapter.getFilter().filter(newText);
57
58 return false;
59 }
60 });
61 }
62}
在上面的代码中,我们将一个月数组列表传递给List Adapter。每次搜索查询文本更改时,我们都会调用Adapter类中定义的Filter方法。Java类如下所示。
1package com.journaldev.searchview;
2
3import android.content.Context;
4import android.databinding.DataBindingUtil;
5import android.view.LayoutInflater;
6import android.view.View;
7import android.view.ViewGroup;
8import android.widget.BaseAdapter;
9import android.widget.Filter;
10import android.widget.Filterable;
11import com.journaldev.searchview.databinding.RowItemBinding;
12import java.util.ArrayList;
13import java.util.List;
14
15public class ListAdapter extends BaseAdapter implements Filterable {
16
17 List<String> mData;
18 List<String> mStringFilterList;
19 ValueFilter valueFilter;
20 private LayoutInflater inflater;
21
22 public ListAdapter(List<String> cancel_type) {
23 mData=cancel_type;
24 mStringFilterList = cancel_type;
25 }
26
27 @Override
28 public int getCount() {
29 return mData.size();
30 }
31
32 @Override
33 public String getItem(int position) {
34 return mData.get(position);
35 }
36
37 @Override
38 public long getItemId(int position) {
39 return position;
40 }
41
42 @Override
43 public View getView(int position, View convertView, final ViewGroup parent) {
44
45 if (inflater == null) {
46 inflater = (LayoutInflater) parent.getContext()
47 .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
48 }
49 RowItemBinding rowItemBinding = DataBindingUtil.inflate(inflater, R.layout.row_item, parent, false);
50 rowItemBinding.stringName.setText(mData.get(position));
51
52 return rowItemBinding.getRoot();
53 }
54
55 @Override
56 public Filter getFilter() {
57 if (valueFilter == null) {
58 valueFilter = new ValueFilter();
59 }
60 return valueFilter;
61 }
62
63 private class ValueFilter extends Filter {
64 @Override
65 protected FilterResults performFiltering(CharSequence constraint) {
66 FilterResults results = new FilterResults();
67
68 if (constraint != null && constraint.length() > 0) {
69 List<String> filterList = new ArrayList<>();
70 for (int i = 0; i < mStringFilterList.size(); i++) {
71 if ((mStringFilterList.get(i).toUpperCase()).contains(constraint.toString().toUpperCase())) {
72 filterList.add(mStringFilterList.get(i));
73 }
74 }
75 results.count = filterList.size();
76 results.values = filterList;
77 } else {
78 results.count = mStringFilterList.size();
79 results.values = mStringFilterList;
80 }
81 return results;
82
83 }
84
85 @Override
86 protected void publishResults(CharSequence constraint,
87 FilterResults results) {
88 mData = (List<String>) results.values;
89 notifyDataSetChanged();
90 }
91
92 }
93
94}
正如你在上面的代码中所看到的,我们正在使用一个扩展Filter类的内部类ValueFilter
来执行过滤。它通过检查搜索查询文本是否与ArrayList中给定的字符串匹配来过滤列表。ListView行的XML布局如下所示。row_item.xml
1<layout xmlns:android="https://schemas.android.com/apk/res/android">
2
3 <RelativeLayout
4 android:layout_width="match_parent"
5 android:layout_height="wrap_content">
6
7 <TextView
8 android:id="@+id/stringName"
9 android:layout_width="wrap_content"
10 android:layout_height="wrap_content"
11 android:layout_alignParentLeft="true"
12 android:layout_alignParentStart="true"
13 android:layout_centerVertical="true"
14 android:padding="@dimen/activity_horizontal_margin"
15 android:textAllCaps="false"
16 android:textAppearance="?android:attr/textAppearanceMedium" />
17
18 </RelativeLayout>
19
20</layout>
Android搜索视图应用程序的实际输出如下所示。上面显示的搜索视图需要我们按下搜索图标来激活文本字段。此外,它不包含任何提示/占位符文本。在MainActivity中添加以下代码以在默认情况下启用SearchView并显示提示。
1activityMainBinding.search.setActivated(true);
2 activityMainBinding.search.setQueryHint("Type your keyword here");
3 activityMainBinding.search.onActionViewExpanded();
4 activityMainBinding.search.setIconified(false);
5 activityMainBinding.search.clearFocus();
按上述方式定制后的SearchView如下所示。这将结束Android SearchView教程。在后面的教程中,我们将深入研究SearchView的高级功能。您可以通过下面的链接下载Android SearchView项目 。