SearchView+Filter對資料進行簡單過濾
阿新 • • 發佈:2018-11-25
轉:https://www.jianshu.com/p/5078c7fec29e
我是使用ListView實現展示系統應用的demo
執行邏輯是這樣的:
- 通過SearchView獲取使用者輸入的文字.
- 把文字傳到Adpater,在Adpater中對關鍵字進行篩選.
- 根據過濾後的結果重新整理RecyclerView顯示過濾後的介面.
先看佈局檔案:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_action" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" tools:context="com.project.granden.enjoy.MyAction.ActionActivity"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?actionBarSize" android:background="#bc4a4a"> <android.support.v7.widget.SearchView android:id="@+id/search_view" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="right"> </android.support.v7.widget.SearchView> </android.support.v7.widget.Toolbar> <android.support.v7.widget.RecyclerView android:id="@+id/recyclerview" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@+id/toolbar"> </android.support.v7.widget.RecyclerView> </RelativeLayout>
一個Toolbar置於頂部裡面包含一個SearchView,剩餘的顯示RecyclerView
然後看程式碼部分:
public class ActionActivity extends AppCompatActivity implements SearchView.OnQueryTextListener { SearchView searchView; Toolbar toolbar; RecyclerView recyclerView; MyAdpater adpter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_action); InitVIew(); recyclerView.setLayoutManager(new LinearLayoutManager(this)); List<String>list=new ArrayList<>(); for (int i = 0; i < 15; i++) { list.add(String.valueOf(i)); } adpter=new MyAdpater(list); recyclerView.setAdapter(adpter); } private void InitVIew() { recyclerView= (RecyclerView) findViewById(R.id.recyclerview); toolbar= (Toolbar) findViewById(R.id.toolbar); searchView= (SearchView) findViewById(R.id.search_view); searchView.setOnQueryTextListener(this); } @Override public boolean onQueryTextSubmit(String query) { return false; } @Override public boolean onQueryTextChange(String newText) { adpter.getFilter().filter(newText); return false; } }
主要看Activity實現的介面:SearchView.OnQueryTextListener
實現該介面後覆寫兩個方法它們的作用就是對SearchView的輸入框進行監聽:
- onQueryTextSubmit 當完成輸入的內容點選搜尋按鈕後該方法會回撥,引數String query返回當前文字框可見的文字
- onQueryTextChange 每次當文字框的內容發生改變該方法會回撥,引數String newText返回當前文字框可見的文字
可以看到我們在onQueryTextChange()方法中呼叫了adpter.getFilter().filter(newText);
他的作用就是對Adpater的內容進行過濾.
每當SearchView的輸入框內容發生變化就把輸入框的內容傳送到Adpater的過濾器接著進行一系列的操作.
public class MyAdpater extends RecyclerView.Adapter<MyAdpater.ViewHolder> implements Filterable {
List number,temp_number;
TestFilter myFilter;
public MyAdpater(List<String> number) {
this.number=number;
temp_number = number;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.test, null);
ViewHolder viewHolder = new ViewHolder(view);
return viewHolder;
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.number.setText((String) number.get(position));
}
@Override
public int getItemCount() {
return number.size();
}
@Override
public Filter getFilter() {
if (myFilter == null) {
myFilter = new TestFilter();
}
return myFilter;
}
class ViewHolder extends RecyclerView.ViewHolder {
TextView number;
public ViewHolder(View itemView) {
super(itemView);
number = (TextView) itemView.findViewById(R.id.number);
}
}
class TestFilter extends Filter {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
List<String> new_number=new ArrayList();
if (constraint != null && constraint.toString().trim().length() > 0) {
for (int i = 0; i < temp_number.size(); i++) {
String content = (String) temp_number.get(i);
if (content.contains(constraint)) {
new_number.add(content);
}
}
}else {
new_number=temp_number;
}
FilterResults filterResults = new FilterResults();
filterResults.count = new_number.size();
filterResults.values = new_number;
return filterResults;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
//這裡對number進行過濾後重新賦值
number = (List) results.values;
//如果過濾後的返回的值的個數大於等於0的話,對Adpater的介面進行重新整理
if (results.count > 0) {
notifyDataSetChanged();
} else {
//否則說明沒有任何過濾的結果,直接提示使用者"沒有符合條件的結果"
umber = new ArrayList(){};
number.add(": ( 沒有符合條件的結果");
notifyDataSetChanged();
}
}
}
}
來看看Adpater的內部:
- MyAdpater(List number)構造方法接收一個List引數
- 並且把number賦值給了temp_number(原因後面會解釋)
- 細心的同學可能早就看到了我們實現了Filterable介面,這個方法需要覆寫getFilter()方法.
public Filter getFilter() {
if (myFilter == null) {
myFilter = new TestFilter();
}
return myFilter;
}
方法需要返回Filter,所以我們新建一個TestFilter類繼承至Filter
class TestFilter extends Filter {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
List<String> new_number=new ArrayList();
if (constraint != null && constraint.toString().trim().length() > 0) {
for (int i = 0; i < temp_number.size(); i++) {
String content = (String) temp_number.get(i);
if (content.contains(constraint)) {
new_number.add(content);
}
}
}else {
new_number=temp_number;
}
FilterResults filterResults = new FilterResults();
filterResults.count = new_number.size();
filterResults.values = new_number;
return filterResults;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
number = (List) results.values;
if (results.count > 0) {
notifyDataSetChanged();
} else {
number.add(": ( 沒有符合條件的結果");
notifyDataSetChanged();
}
}
}
Filter類裡面有兩個方法:
performFiltering:引數constraint是adpter.getFilter().filter(newText)方法傳入的newText(也就是過濾的條件)
該方法主要完成對資料進行過濾的工作
publishResults:引數CharSequence,results第一個引數這裡不需要用到,第二個引數是上面的performFiltering返回的值.
在該方法裡面進行介面的重新整理工作
裡面實現的思路是:
- 新建一個List new_number這個物件用來儲存過濾後符合條件的值
- 判斷constraint是否為空,是否有值.滿足條件的話遍歷List,並且判斷List的值是否有包含過濾的條件.如果是的話把值存到new_number.如果一個符合的都沒有把temp_number的值(也就是最開始傳進來的List)賦值給new_number
- 新建一個FilterResults物件分別把new_number的size和value賦值給FilterResults.value和FilterResults.count,然後返回FilterResults物件
- 接著在publishResults()方法中取出過濾後滿足條件的值也就是results.values
- 判斷results.count的過濾後結果的個數是否大於0
- 大於0的話把值賦值給number然後重新整理介面,不滿足的話把temp_number(也就是最開始傳進來的值)賦值給number,然後重新整理介面