Пользовательский адаптер Listview с фильтром Android

Я пытаюсь реализовать фильтр в своем списке. Но всякий раз, когда текст меняется, список исчезает. Пожалуйста, помогите. Вот мои коды. Класс адаптера.

package com.talagbe.schymn; import java.util.ArrayList; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.TextView; public class HymnsAdapter extends ArrayAdapter<Hymns> { ArrayList<Hymns> hymnarray; Context context; LayoutInflater inflater; int Resource; public HymnsAdapter(Context context, int resource, ArrayList<Hymns> objects) { super(context, resource, objects); // TODO Auto-generated constructor stub hymnarray=objects; Resource= resource; this.context=context; inflater= (LayoutInflater) context.getSystemService(context.LAYOUT_INFLATER_SERVICE); } @Override public View getView(int position, View convertView, ViewGroup parent) { // TODO Auto-generated method stub ViewHolder holder; if(convertView==null){ convertView= inflater.inflate(Resource,null); holder= new ViewHolder(); holder.hymntitle= (TextView) convertView.findViewById(R.id.Hymn_title); // holder.hymntext= (TextView) convertView.findViewById(R.id.Channel_name); convertView.setTag(holder); }else{ holder=(ViewHolder)convertView.getTag(); } holder.hymntitle.setText(hymnarray.get(position).getTitle()); //holder.hymntext.setText(hymnarray.get(position).getText()); return convertView; } static class ViewHolder{ public TextView hymntitle; public TextView hymntext; } } 

Вот другой класс, где я пытаюсь реализовать фильтр. У меня есть edittext, где я реализую на textChangeListener

 package com.talagbe.schymn; import java.util.ArrayList; import database.DatabaseHelper; import android.os.Bundle; import android.support.v4.app.Fragment; import android.text.Editable; import android.text.TextWatcher; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.EditText; import android.widget.ListView; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.widget.AdapterView.OnItemClickListener; public class Home extends Fragment { private static final String DB_NAME = "schymn.sqlite"; private static final String TABLE_NAME = "Hymns"; private static final String Hymn_ID = "_id"; private static final String Hymn_Title = "Title"; private static final String Hymn_Text = "Text"; private SQLiteDatabase database; ListView list; EditText search; HymnsAdapter vadapter; ArrayList<Hymns> HymnsList; String url; Context context=null; public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // TODO Auto-generated method stub return inflater.inflate(R.layout.index, container,false); } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onCreate(savedInstanceState); list = (ListView)getActivity().findViewById(R.id.hymn_list); search = (EditText) getActivity().findViewById(R.id.search); HymnsList = new ArrayList<Hymns>(); DatabaseHelper dbOpenHelper = new DatabaseHelper(getActivity(), DB_NAME); database = dbOpenHelper.openDataBase(); fillHymns(); //setUpList(); } private void fillHymns() { Cursor hymnCursor = database.query(TABLE_NAME, new String[] {Hymn_ID, Hymn_Title,Hymn_Text}, null, null, null, null , Hymn_Title); hymnCursor.moveToFirst(); if(!hymnCursor.isAfterLast()) { do { Hymns hy = new Hymns(); hy.setTitle(hymnCursor.getString(1)); hy.setText(hymnCursor.getString(2)); HymnsList.add(hy); } while (hymnCursor.moveToNext()); } hymnCursor.close(); vadapter = new HymnsAdapter(getActivity().getApplicationContext(),R.layout.hymns,HymnsList); list.setAdapter(vadapter); list.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Intent intent = new Intent(getActivity().getApplicationContext(), Hymn_Text.class); intent.putExtra("Title",HymnsList.get(position).getTitle()); intent.putExtra("Text",HymnsList.get(position).getText()); startActivity(intent); //Log.i("Text",HymnsList.get(position).getText()); } }); search.addTextChangedListener( new TextWatcher() { @Override public void onTextChanged(CharSequence cs, int start, int before, int count) { // TODO Auto-generated method stub if(count>0){ } } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { // TODO Auto-generated method stub } @Override public void afterTextChanged(Editable s) { // TODO Auto-generated method stub Home.this.vadapter.getFilter().filter(s); Log.i("Changed",s.toString()); } }); } } 

Журнал, регистрирует любой вход, который я вводил, но не отображает список. спасибо

Solutions Collecting From Web of "Пользовательский адаптер Listview с фильтром Android"

Вы можете использовать интерфейс Filterable на вашем адаптере, см. Хороший пример ниже:

Оригинальный источник и см. Другой пример здесь

 public class SearchableAdapter extends BaseAdapter implements Filterable { private List<String>originalData = null; private List<String>filteredData = null; private LayoutInflater mInflater; private ItemFilter mFilter = new ItemFilter(); public SearchableAdapter(Context context, List<String> data) { this.filteredData = data ; this.originalData = data ; mInflater = LayoutInflater.from(context); } public int getCount() { return filteredData.size(); } public Object getItem(int position) { return filteredData.get(position); } public long getItemId(int position) { return position; } public View getView(int position, View convertView, ViewGroup parent) { // A ViewHolder keeps references to children views to avoid unnecessary calls // to findViewById() on each row. ViewHolder holder; // When convertView is not null, we can reuse it directly, there is no need // to reinflate it. We only inflate a new View when the convertView supplied // by ListView is null. if (convertView == null) { convertView = mInflater.inflate(R.layout.list_item, null); // Creates a ViewHolder and store references to the two children views // we want to bind data to. holder = new ViewHolder(); holder.text = (TextView) convertView.findViewById(R.id.list_view); // Bind the data efficiently with the holder. convertView.setTag(holder); } else { // Get the ViewHolder back to get fast access to the TextView // and the ImageView. holder = (ViewHolder) convertView.getTag(); } // If weren't re-ordering this you could rely on what you set last time holder.text.setText(filteredData.get(position)); return convertView; } static class ViewHolder { TextView text; } public Filter getFilter() { return mFilter; } private class ItemFilter extends Filter { @Override protected FilterResults performFiltering(CharSequence constraint) { String filterString = constraint.toString().toLowerCase(); FilterResults results = new FilterResults(); final List<String> list = originalData; int count = list.size(); final ArrayList<String> nlist = new ArrayList<String>(count); String filterableString ; for (int i = 0; i < count; i++) { filterableString = list.get(i); if (filterableString.toLowerCase().contains(filterString)) { nlist.add(filterableString); } } results.values = nlist; results.count = nlist.size(); return results; } @SuppressWarnings("unchecked") @Override protected void publishResults(CharSequence constraint, FilterResults results) { filteredData = (ArrayList<String>) results.values; notifyDataSetChanged(); } } } //in your Activity or Fragment where of Adapter is instantiated : editTxt.addTextChangedListener(new TextWatcher() { @Override public void onTextChanged(CharSequence s, int start, int before, int count) { System.out.println("Text ["+s+"]"); mSearchableAdapter.getFilter().filter(s.toString()); } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void afterTextChanged(Editable s) { } }); 

Я надеюсь, что это будет полезно для других.

 // put below code (method) in Adapter class public void filter(String charText) { charText = charText.toLowerCase(Locale.getDefault()); myList.clear(); if (charText.length() == 0) { myList.addAll(arraylist); } else { for (MyBean wp : arraylist) { if (wp.getName().toLowerCase(Locale.getDefault()).contains(charText)) { myList.add(wp); } } } notifyDataSetChanged(); } 

Объявить ниже код в классе адаптера

 private ArrayList<MyBean> myList; // for loading main list private ArrayList<MyBean> arraylist=null; // for loading filter data 

Ниже кода в адаптере Конструктор

 this.arraylist = new ArrayList<MyBean>(); this.arraylist.addAll(myList); 

И ниже кода в вашем классе активности

 final EditText searchET = (EditText)findViewById(R.id.search_et); // Capture Text in EditText searchET.addTextChangedListener(new TextWatcher() { @Override public void afterTextChanged(Editable arg0) { // TODO Auto-generated method stub String text = searchET.getText().toString().toLowerCase(Locale.getDefault()); adapter.filter(text); } @Override public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) { // TODO Auto-generated method stub } @Override public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) { // TODO Auto-generated method stub } }); 

Проверьте ниже код, это поможет вам

 DrawerActivity.userListview .setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { int pos = position; Intent intent = new Intent(getContext(), UserDetail.class); intent.putExtra("model", list.get(position)); context.startActivity(intent); } }); return convertView; } @Override public android.widget.Filter getFilter() { return new android.widget.Filter() { @Override protected void publishResults(CharSequence constraint, FilterResults results) { ArrayList<UserListModel> updatelist = (ArrayList<UserListModel>) results.values; UserListCustomAdaptor newadaptor = new UserListCustomAdaptor( getContext(), getCount(), updatelist); if (results.equals(constraint)) { updatelist.add(modelobj); } if (results.count > 0) { notifyDataSetChanged(); } else { notifyDataSetInvalidated(); } } @Override protected FilterResults performFiltering(CharSequence constraint) { FilterResults filterResults = new FilterResults(); list = new ArrayList<UserListModel>(); if (constraint != null && DrawerActivity.userlist != null) { constraint = constraint.toString().toLowerCase(); int length = DrawerActivity.userlist.size(); int i = 0; while (i < length) { UserListModel modelobj = DrawerActivity.userlist.get(i); String data = modelobj.getFirstName() + " " + modelobj.getLastName(); if (data.toLowerCase().contains(constraint.toString())) { list.add(modelobj); } i++; } filterResults.values = list; filterResults.count = list.size(); } return filterResults; } }; } @Override public int getCount() { return list.size(); } @Override public UserListModel getItem(int position) { return list.get(position); } 

Сначала вы создаете EditText в XML-файле и назначаете идентификатор, например con_pag_etPesquisa. После этого мы создадим два списка, в которых один представляет собой список, а другой – для получения одного и того же содержимого, но останется резервным. Прежде чем перемещать объекты в списки сначала инициализирует их ниже:

 //Declaring public EditText etPesquisa; public ContasPagarAdapter adapterNormal; public List<ContasPagar> lstBkp; public List<ContasPagar> lstCp; //Within the onCreate method, type the following: etPesquisa = (EditText) findViewById(R.id.con_pag_etPesquisa); etPesquisa.addTextChangedListener(new TextWatcher(){ @Override public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3){ filter(String.valueOf(cs)); } @Override public void beforeTextChanged(CharSequence cs, int arg1, int arg2, int arg3){ // TODO Auto-generated method stub } @Override public void afterTextChanged(Editable e){ } }); //Before moving objects to lists first initializes them as below: lstCp = new ArrayList<ContasPagar>(); lstBkp = new ArrayList<ContasPagar>(); //When you add objects to the main list, repeat the procedure also for bkp list, as follows: lstCp.add(cp); lstBkp.add(cp); //Now initializes the adapter and let the listener, as follows: adapterNormal = new ContasPagarAdapter(ContasPagarActivity.this, lstCp); lvContasPagar.setAdapter(adapterNormal); lvContasPagar.setOnItemClickListener(verificaClickItemContasPagar(lstCp)); //Now create the methods inside actito filter the text entered by the user, as follows: public void filter(String charText){ charText = charText.toLowerCase(); lstCp.clear(); if (charText.length() == 0){ lstCp.addAll(lstBkp); appendAddItem(lstBkp); } else { for (int i = 0; i < lstBkp.size(); i++){ if((lstBkp.get(i).getNome_lancamento() + " - " + String.valueOf(lstBkp.get(i).getCodigo())).toLowerCase().contains(charText)){ lstCp.add(lstBkp.get(i)); } } appendAddItem(lstCp); } } private void appendAddItem(final List<ContasPagar> novaLista){ runOnUiThread(new Runnable(){ @Override public void run(){ adapterNormal.notifyDataSetChanged(); } }); } 

Вы можете найти собственный класс адаптера списка с возможностью фильтрации с помощью изменения текста в текстовом редакторе …

Создать класс адаптера пользовательского списка с реализацией Filterable:

 private class CustomListAdapter extends BaseAdapter implements Filterable{ private LayoutInflater inflater; private ViewHolder holder; private ItemFilter mFilter = new ItemFilter(); public CustomListAdapter(List<YourCustomData> newlist) { filteredData = newlist; } @Override public int getCount() { return filteredData.size(); } @Override public Object getItem(int position) { return null; } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { holder = new ViewHolder(); if(inflater==null) inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE); if(convertView == null){ convertView = inflater.inflate(R.layout.row_listview_item, null); holder.mTextView = (TextView)convertView.findViewById(R.id.row_listview_member_tv); convertView.setTag(holder); }else{ holder = (ViewHolder)convertView.getTag(); } holder.mTextView.setText(""+filteredData.get(position).getYourdata()); return convertView; } @Override public Filter getFilter() { return mFilter; } } class ViewHolder{ TextView mTextView; } private class ItemFilter extends Filter { @SuppressLint("DefaultLocale") @Override protected FilterResults performFiltering(CharSequence constraint) { String filterString = constraint.toString().toLowerCase(); FilterResults results = new FilterResults(); final List<YourCustomData> list = YourObject.getYourDataList(); int count = list.size(); final ArrayList<YourCustomData> nlist = new ArrayList<YourCustomData>(count); String filterableString ; for (int i = 0; i < count; i++) { filterableString = ""+list.get(i).getYourText(); if (filterableString.toLowerCase().contains(filterString)) { YourCustomData mYourCustomData = list.get(i); nlist.add(mYourCustomData); } } results.values = nlist; results.count = nlist.size(); return results; } @SuppressWarnings("unchecked") @Override protected void publishResults(CharSequence constraint, FilterResults results) { filteredData = (ArrayList<YourCustomData>) results.values; mCustomListAdapter.notifyDataSetChanged(); } } mEditTextSearch.addTextChangedListener(new TextWatcher() { @Override public void onTextChanged(CharSequence s, int start, int before, int count) { if(mCustomListAdapter!=null) mCustomListAdapter.getFilter().filter(s.toString()); } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void afterTextChanged(Editable s) { } }); 

Я заметил, что всякий раз, когда вы редактируете список (например, добавляете элементы), а также фильтруете его, то внутри метода @Override getView вы не должны использовать @Override getView filteredData.get(position) , поскольку оно выбрасывает Исключение IndexOutOfBounds .

Вместо этого то, что сработало для меня, использовало метод getItem(position) , который принадлежит классу ArrayAdapter .

Вы можете реализовать фильтр поиска в виде списка двумя способами. 1. используя searchview 2. с помощью edittext.

  1. Если вы хотите использовать searchview, читайте здесь: searchview filter.

  2. Если вы хотите использовать edittext, читайте ниже.

Я взял ссылку на: listview search filter android

Фрагменты кода для создания фильтра с помощью edittext.

Сначала создайте класс модели MovieNames.java:

 public class MovieNames { private String movieName; public MovieNames(String movieName) { this.movieName = movieName; } public String getMovieName() { return this.movieName; } } 

Создайте файл listview_item.xml:

  <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:padding="10dp"> <TextView android:id="@+id/name" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </RelativeLayout> 

Сделать класс ListViewAdapter.java:

  import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.TextView; import java.util.ArrayList; import java.util.Locale; public class ListViewAdapter extends BaseAdapter { // Declare Variables Context mContext; LayoutInflater inflater; private ArrayList<MovieNames> arraylist; public ListViewAdapter(Context context, ArrayList<MovieNames> arraylist) { mContext = context; inflater = LayoutInflater.from(mContext); this.arraylist = arraylist; } public class ViewHolder { TextView name; } @Override public int getCount() { return arraylist.size(); } @Override public MovieNames getItem(int position) { return arraylist.get(position); } @Override public long getItemId(int position) { return position; } public View getView(final int position, View view, ViewGroup parent) { final ViewHolder holder; if (view == null) { holder = new ViewHolder(); view = inflater.inflate(R.layout.listview_item, null); // Locate the TextViews in listview_item.xml holder.name = (TextView) view.findViewById(R.id.name); view.setTag(holder); } else { holder = (ViewHolder) view.getTag(); } // Set the results into TextViews holder.name.setText(arraylist.get(position).getMovieName()); return view; } } 

Подготовьте файл activity_main.xml:

  <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.example.parsaniahardik.searchedit.MainActivity" android:orientation="vertical"> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/editText" android:layout_alignParentTop="true" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:hint="enter query" android:singleLine="true"> <requestFocus/> </EditText> <ListView android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/listView" android:divider="#694fea" android:dividerHeight="1dp" /> </LinearLayout> 

Наконец, сделайте класс MainActivity.java:

  import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.text.Editable; import android.text.TextWatcher; import android.util.Log; import android.view.View; import android.widget.AdapterView; import android.widget.EditText; import android.widget.ListView; import android.widget.SearchView; import android.widget.Toast; import java.util.ArrayList; public class MainActivity extends AppCompatActivity { private EditText etsearch; private ListView list; private ListViewAdapter adapter; private String[] moviewList; public static ArrayList<MovieNames> movieNamesArrayList; public static ArrayList<MovieNames> array_sort; int textlength = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Generate sample data moviewList = new String[]{"Xmen", "Titanic", "Captain America", "Iron man", "Rocky", "Transporter", "Lord of the rings", "The jungle book", "Tarzan","Cars","Shreck"}; list = (ListView) findViewById(R.id.listView); movieNamesArrayList = new ArrayList<>(); array_sort = new ArrayList<>(); for (int i = 0; i < moviewList.length; i++) { MovieNames movieNames = new MovieNames(moviewList[i]); // Binds all strings into an array movieNamesArrayList.add(movieNames); array_sort.add(movieNames); } adapter = new ListViewAdapter(this,movieNamesArrayList); list.setAdapter(adapter); etsearch = (EditText) findViewById(R.id.editText); list.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Toast.makeText(MainActivity.this, array_sort.get(position).getMovieName(), Toast.LENGTH_SHORT).show(); } }); etsearch.addTextChangedListener(new TextWatcher() { public void afterTextChanged(Editable s) { } public void beforeTextChanged(CharSequence s, int start, int count, int after) { } public void onTextChanged(CharSequence s, int start, int before, int count) { textlength = etsearch.getText().length(); array_sort.clear(); for (int i = 0; i < movieNamesArrayList.size(); i++) { if (textlength <= movieNamesArrayList.get(i).getMovieName().length()) { Log.d("ertyyy",movieNamesArrayList.get(i).getMovieName().toLowerCase().trim()); if (movieNamesArrayList.get(i).getMovieName().toLowerCase().trim().contains( etsearch.getText().toString().toLowerCase().trim())) { array_sort.add(movieNamesArrayList.get(i)); } } } adapter = new ListViewAdapter(MainActivity.this, array_sort); list.setAdapter(adapter); } }); } }