使用DataBinding的Android SearchView示例教程
今天,我们将研究Android SearchView小部件,并开发一个应用程序,该应用程序可通过查询的文本过滤ListView。
我们将使用DataBinding来连接"活动"和"适配器"中的布局。
如果您尚未阅读有关DataBinding的信息,请先参阅本教程以获取更好的理解。
Android SearchView
Android通过在ToolBar/ActionBar中显示SearchView小部件或者将其插入到布局中来允许我们在应用中使用搜索功能。
从Android 3.0开始可以使用Android SearchView小部件。
SearchView在XML布局中定义,如下所示。
<android.support.v7.widget.SearchView android:id="@+id/search" android:layout_width="match_parent" android:layout_height="wrap_content"
Android中有多种搜索形式,例如语音搜索,建议等。
在本教程中,我们将使用SearchView.OnQueryTextListener和Filterable接口。
Filterable接口过滤ListView上查询的文本,并显示结果ListView行。
OnQueryTextListener接口可以检测两个事件。
- 当用户在文本字段中键入每个字符时,就会调用onQueryTextChange
- 按下搜索时会触发onQueryTextSubmit
Android SearchView示例
下图显示了最终的Android SearchView示例项目。
该项目由一个Activity和一个用于ListView的适配器组成。
Android SearchView示例代码
下面给出activity_main.xml。
它由一个ListView和一个顶部的SearchView组成。
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="https://schemas.android.com/apk/res/android"> <RelativeLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <android.support.v7.widget.SearchView android:id="@+id/search" android:layout_width="match_parent" android:layout_height="wrap_content" android:clickable="true" <ListView android:id="@+id/list_view" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_below="@+id/search" </RelativeLayout> </layout>
MainActivity.java在下面给出。
package com.theitroad.searchview; import android.databinding.DataBindingUtil; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.support.v7.widget.SearchView; import com.theitroad.searchview.databinding.ActivityMainBinding; import java.util.ArrayList; import java.util.List; public class MainActivity extends AppCompatActivity { ActivityMainBinding activityMainBinding; ListAdapter adapter; List<String> arrayList= new ArrayList<>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); activityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main); arrayList.add("January"); arrayList.add("February"); arrayList.add("March"); arrayList.add("April"); arrayList.add("May"); arrayList.add("June"); arrayList.add("July"); arrayList.add("August"); arrayList.add("September"); arrayList.add("October"); arrayList.add("November"); arrayList.add("December"); adapter= new ListAdapter(arrayList); activityMainBinding.listView.setAdapter(adapter); activityMainBinding.search.setActivated(true); activityMainBinding.search.setQueryHint("Type your keyword here"); activityMainBinding.search.onActionViewExpanded(); activityMainBinding.search.setIconified(false); activityMainBinding.search.clearFocus(); activityMainBinding.search.setOnQueryTextListener(new SearchView.OnQueryTextListener() { @Override public boolean onQueryTextSubmit(String query) { return false; } @Override public boolean onQueryTextChange(String newText) { adapter.getFilter().filter(newText); return false; } }); } }
在上面的代码中,我们将一个ArrayList of Months传递给列表适配器。
每次搜索查询文本更改时,我们都会调用适配器类中定义的过滤器方法。
ListAdapter.java类如下所示。
package com.theitroad.searchview; import android.content.Context; import android.databinding.DataBindingUtil; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.Filter; import android.widget.Filterable; import com.theitroad.searchview.databinding.RowItemBinding; import java.util.ArrayList; import java.util.List; public class ListAdapter extends BaseAdapter implements Filterable { List<String> mData; List<String> mStringFilterList; ValueFilter valueFilter; private LayoutInflater inflater; public ListAdapter(List<String> cancel_type) { mData=cancel_type; mStringFilterList = cancel_type; } @Override public int getCount() { return mData.size(); } @Override public String getItem(int position) { return mData.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, final ViewGroup parent) { if (inflater == null) { inflater = (LayoutInflater) parent.getContext() .getSystemService(Context.LAYOUT_INFLATER_SERVICE); } RowItemBinding rowItemBinding = DataBindingUtil.inflate(inflater, R.layout.row_item, parent, false); rowItemBinding.stringName.setText(mData.get(position)); return rowItemBinding.getRoot(); } @Override public Filter getFilter() { if (valueFilter == null) { valueFilter = new ValueFilter(); } return valueFilter; } private class ValueFilter extends Filter { @Override protected FilterResults performFiltering(CharSequence constraint) { FilterResults results = new FilterResults(); if (constraint != null && constraint.length() > 0) { List<String> filterList = new ArrayList<>(); for (int i = 0; i < mStringFilterList.size(); i++) { if ((mStringFilterList.get(i).toUpperCase()).contains(constraint.toString().toUpperCase())) { filterList.add(mStringFilterList.get(i)); } } results.count = filterList.size(); results.values = filterList; } else { results.count = mStringFilterList.size(); results.values = mStringFilterList; } return results; } @Override protected void publishResults(CharSequence constraint, FilterResults results) { mData = (List<String>) results.values; notifyDataSetChanged(); } } }
如您在上面的代码中看到的,我们正在使用内部类" ValueFilter"执行过滤,该内部类扩展了Filter类。
它通过检查搜索查询文本是否与ArrayList中给出的字符串匹配来过滤列表。
下面给出了ListView行的XML布局。
row_item.xml
<layout xmlns:android="https://schemas.android.com/apk/res/android"> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/stringName" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_centerVertical="true" android:padding="@dimen/activity_horizontal_margin" android:textAllCaps="false" android:textAppearance="?android:attr/textAppearanceMedium" </RelativeLayout> </layout>
运行中的android search view应用程序的输出如下。
上面显示的SearchView要求我们按搜索图标以激活文本字段。
另外,它不包含任何提示/占位符文本。
在MainActivity中添加以下代码以默认情况下启用SearchView并显示提示。
activityMainBinding.search.setActivated(true); activityMainBinding.search.setQueryHint("Type your keyword here"); activityMainBinding.search.onActionViewExpanded(); activityMainBinding.search.setIconified(false); activityMainBinding.search.clearFocus();