android search filter android-recyclerview android-adapter

Android: implementación del filtro de búsqueda en un RecyclerView



search filter (3)

Necesito implementar una función de búsqueda basada en EditText en mi RecyclerView . La lista se debe filtrar mientras se escribe.

Aquí está el código:

DisplayAdapter.java este es el adaptador

public class DisplayAdapter extends RecyclerView.Adapter<DisplayAdapter.MyViewHolder>{ private List<DataHolder> displayedList; public class MyViewHolder extends RecyclerView.ViewHolder{ public TextView english_d; public MyViewHolder(View view){ super(view); english_d = (TextView) view.findViewById(R.id.engword); } } public DisplayAdapter(List<DataHolder> displayedList){ this.displayedList = displayedList; } @Override public MyViewHolder onCreateViewHolder(ViewGroup parent, int position) { // create a layout View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item, parent, false); return new MyViewHolder(itemView); } @Override public void onBindViewHolder(MyViewHolder holder, int position) { DataHolder content = displayedList.get(position); holder.english_d.setText(content.getEnglish()); } @Override public int getItemCount() { return displayedList.size(); } }

DataHolder.java

public class DataHolder { private String english; public DataHolder() { } public DataHolder(String english, String norse) { this.english = english; } public String getEnglish() { return english; } public void setEnglish(String english) { this.english = english; } }

y aquí está el Fragmento con el que estoy trabajando:

@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.activity_two_fragment, container, false); rv = (RecyclerView) view.findViewById(R.id.list_view_english); rv.setHasFixedSize(true); inputSearch = (EditText) view.findViewById(R.id.inputSearch); rv.addItemDecoration(new DividerItemDecoration(getActivity(), LinearLayoutManager.VERTICAL)); final LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false); rv.setLayoutManager(layoutManager); DisplayContent(); disp_adapter = new DisplayAdapter(displayedList); rv.setAdapter(disp_adapter); return view; }


en su adaptador agregue una nueva función para actualizar la lista

public void updateList(List<DataHolder> list){ displayedList = list; notifyDataSetChanged(); }

agregar textWatcher para la búsqueda, digamos que está usando Edittext como campo de búsqueda

searchField.addTextChangedListener(new TextWatcher() { @Override public void onTextChanged(CharSequence s, int start, int before, int count) { // TODO Auto-generated method stub } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { // TODO Auto-generated method stub } @Override public void afterTextChanged(Editable s) { // filter your list from your input filter(s.toString()); //you can use runnable postDelayed like 500 ms to delay search text } });

Función de filtro simple

void filter(String text){ List<DataHolder> temp = new ArrayList(); for(DataHolder d: displayedList){ //or use .equal(text) with you want equal match //use .toLowerCase() for better matches if(d.getEnglish().contains(text)){ temp.add(d); } } //update recyclerview disp_adapter.updateList(temp); }


Con navaja

@OnTextChanged(R.id.feature_manager_search) protected void onTextChanged(CharSequence text) { filter(text.toString()); }


he hecho asi

Archivo .XMl

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <android.support.design.widget.AppBarLayout android:id="@+id/appBar" android:layout_width="match_parent" android:layout_height="wrap_content" app:elevation="1dp" android:theme="@style/AppTheme.AppBarOverlay" android:layout_marginBottom="@dimen/bottom_margin"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:popupTheme="@style/AppTheme.PopupOverlay"/> </android.support.design.widget.AppBarLayout> <EditText android:id="@+id/etSearch" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Search" android:imeOptions="actionDone" android:singleLine="true"/> <android.support.v7.widget.RecyclerView android:id="@+id/rvCategory" android:layout_width="match_parent" android:layout_height="match_parent"> </android.support.v7.widget.RecyclerView> </LinearLayout>

Archivo de clase .JAVA

package com.example.myapplication; import android.content.Context; import android.content.Intent; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.support.v7.widget.CardView; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.Toolbar; import android.text.Editable; import android.text.TextWatcher; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.EditText; import android.widget.Filter; import android.widget.Filterable; import android.widget.ImageView; import android.widget.TextView; import org.json.JSONObject; import java.util.ArrayList; public class Home extends AppCompatActivity implements ResultCallBack{ SQLiteDatabase db; ArrayList<String> alCategorName=new ArrayList<>(); RecyclerView rvCategory; EditText etSearch; Category bookadapter; ArrayList<String> alBookInfo; String strURL="http://localhost:21246/api/TreasuryBooks?BookId=1"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_home); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); toolbar.setTitleTextColor(getResources().getColor(R.color.white)); setSupportActionBar(toolbar); // AsyncTask_WebAPI asyncTask=new AsyncTask_WebAPI(this,strURL,this); // asyncTask.execute(); etSearch=(EditText)findViewById(R.id.etSearch); etSearch.setText(""); DatabaseAccess da= DatabaseAccess.getInstance(this); db=da.open(); alBookInfo=new ArrayList<String>(); Cursor c = db.rawQuery("select BookName from Books", null); int rows = c.getCount(); c.moveToFirst(); for(int i=0;i<rows;i++) { String strBoookName=c.getString(c.getColumnIndex("BookName")); alBookInfo.add(strBoookName); c.moveToNext(); } c.close(); db.close(); rvCategory=(RecyclerView)findViewById(R.id.rvCategory); //Recycler view adapter bookadapter=new Category(this,alBookInfo); rvCategory.setLayoutManager(new LinearLayoutManager(this)); rvCategory.setAdapter(bookadapter); //text change listner etSearch.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { bookadapter.getFilter().filter(s.toString()); } @Override public void afterTextChanged(Editable s) { } }); } @Override public void onBackPressed() { Home.this.finish(); } @Override protected void onRestart() { super.onRestart(); etSearch.setText(""); } @Override public void onResultListener(Object object) { JSONObject jsonObject=(JSONObject)object; try { String strId = jsonObject.getString("id"); String strBookId=jsonObject.getString("BookId"); String strBookName=jsonObject.getString("BookName"); db.rawQuery("insert into Books values(''"+strId+"'',''"+strBookId+"'',''"+strBookName+"''",null); } catch (Exception e) { e.printStackTrace(); } }

Adaptador Recyclerview

//Recycler view adapter Class with filterable interface private class Category extends RecyclerView.Adapter<viewHolder> implements Filterable { ArrayList<String> alBooks=new ArrayList<String>(); Context context; viewHolder holder; public Category() {} public Category(Context context,ArrayList<String> albooks) { this.context=context; this.alBooks=albooks; } @Override public int getItemCount() { return alBooks.size(); } @Override public viewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View v= LayoutInflater.from(parent.getContext()).inflate(R.layout.home_cardview,parent,false); holder=new viewHolder(v); return holder; } @Override public void onBindViewHolder(viewHolder holder, int position) { holder.tvBookName.setText(alBooks.get(position)); } private Filter fRecords; //return the filter class object @Override public Filter getFilter() { if(fRecords == null) { fRecords=new RecordFilter(); } return fRecords; } //filter class private class RecordFilter extends Filter { @Override protected FilterResults performFiltering(CharSequence constraint) { FilterResults results = new FilterResults(); //Implement filter logic // if edittext is null return the actual list if (constraint == null || constraint.length() == 0) { //No need for filter results.values = alBookInfo; results.count = alBookInfo.size(); } else { //Need Filter // it matches the text entered in the edittext and set the data in adapter list ArrayList<String> fRecords = new ArrayList<String>(); for (String s : alBookInfo) { if (s.toUpperCase().trim().contains(constraint.toString().toUpperCase().trim())) { fRecords.add(s); } } results.values = fRecords; results.count = fRecords.size(); } return results; } @Override protected void publishResults(CharSequence constraint,FilterResults results) { //it set the data from filter to adapter list and refresh the recyclerview adapter alBooks = (ArrayList<String>) results.values; notifyDataSetChanged(); } } } private class viewHolder extends RecyclerView.ViewHolder { CardView cv; TextView tvBookName; viewHolder(final View itemview) { super(itemview); cv = (CardView) itemview.findViewById(R.id.cardview); tvBookName = (TextView) itemview.findViewById(R.id.categoryName); itemview.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent=new Intent(Home.this,Act_Fragment_Container.class); intent.putExtra("BookName", tvBookName.getText()); startActivity(intent); } }); } }

}

agregue el adaptador de vista de reciclador en la misma clase para evitar confusiones ...


implementar SearchView.OnQueryTextListner

public class Countries_List extends AppCompatActivity implements SearchView.OnQueryTextListener //your Model Class List<Countries> dataList, filteredDataList; @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu_main, menu); MenuItem item=menu.findItem(R.id.action_search); SearchView searchView=(SearchView)MenuItemCompat.getActionView(item); searchView.setOnQueryTextListener(this); return true; } @Override public boolean onQueryTextSubmit(String query) { return false; } @Override public boolean onQueryTextChange(String newText) { filteredDataList = filter(dataList, newText); mAdapter.setFilter(filteredDataList); return true; } public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); //noinspection SimplifiableIfStatement if (id == R.id.action_search) { return true; } return super.onOptionsItemSelected(item); } private List<Countries> filter(List<Countries> dataList, String newText) { newText=newText.toLowerCase(); String text; filteredDataList=new ArrayList<>(); for(Countries dataFromDataList:dataList){ text=dataFromDataList.getTitle().toLowerCase(); if(text.contains(newText)){ filteredDataList.add(dataFromDataList); } } return filteredDataList; }

en su clase de adaptador:

void setFilter(List<Countries> FilteredDataList) { countriesList = FilteredDataList; notifyDataSetChanged(); }