今天我們將研究 Android SearchView widget,並開發一個可以通過查詢文本來過濾 ListView 的應用程序。我們將使用 DataBinding 將佈局與活動和適配器連接起來。如果你還沒有閱讀有關 DataBinding 的教程,請先閱讀 這個 教程以更好地理解。
Android SearchView
Android 允許我們在應用程序中使用搜索功能,可以將 SearchView widget 顯示在工具欄/操作欄上,也可以將其插入到佈局中。Android SearchView widget 從 Android 3.0 開始提供。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使用的適配器(Adapter)。
Android SearchView範例代碼
activity_main.xml如下所示。它包括一個帶有SearchView的ListView。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.journaldev.searchview;
import android.databinding.DataBindingUtil;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.SearchView;
import com.journaldev.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傳遞給列表適配器(List Adapter)。每次搜索查詢文本更改時,我們都會調用適配器類中定義的filter方法。ListAdapter.java類看起來像這樣。
package com.journaldev.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.journaldev.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();
}
}
}
正如您在上面的代碼中所看到的,我們使用擴展Filter類的內部類ValueFilter
來執行篩選。它通過檢查搜索查詢文本是否與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 搜索视图应用程序的操作输出。如上所示的 SearchView 需要我们按下搜索图标才能激活文本字段。此外,它不包含任何提示/占位文本。在 MainActivity 中添加以下代码以默认启用 SearchView 并显示提示。
activityMainBinding.search.setActivated(true);
activityMainBinding.search.setQueryHint("Type your keyword here");
activityMainBinding.search.onActionViewExpanded();
activityMainBinding.search.setIconified(false);
activityMainBinding.search.clearFocus();
以上自定义后的 SearchView 看起来像这样。这就结束了 Android SearchView 教程。我们将在以后的教程中深入介绍 SearchView 的高级功能。您可以从以下链接下载Android SearchView 项目。
Source:
https://www.digitalocean.com/community/tutorials/android-searchview-example-tutorial