Пользовательский адаптер 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 { ArrayList hymnarray; Context context; LayoutInflater inflater; int Resource; public HymnsAdapter(Context context, int resource, ArrayList 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; } }
Вот другой class, где я пытаюсь реализовать фильтр. У меня есть 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 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(); 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()); } }); } }
Журнал, регистрирует любой вход, который я вводил, но не отображает список. спасибо
- Есть ли разница между «ListView.invalidateViews ()» и «Adapter.notifyDataSetChanged ()»?
- Как реализовать поиск в CustomListView на основе classа classа POJO в Android?
- Преобразование JSONarray в ArrayList
- Обнаружение прокрутки вверх и прокрутка вниз в ListView
- Android: кнопка «Радио» в пользовательском списке
- Android получает точную позицию прокрутки в ListView
- Пользовательский getFilter в пользовательском ArrayAdapter в android
- Как выделить строку в ListView в Android?
- как установить режим выбора для списка с изображениями
- Справка относительно события onClick () для элемента пользовательской строки списка ListView
- Как добавить нижний колонтитул в ListView?
- Использование ListView: как добавить представление заголовка?
- ListFragment не принимает мой макет
Вы можете использовать интерфейс Filterable на вашем адаптере, см. Хороший пример ниже:
оригинальный источник и см. другой пример здесь
public class SearchableAdapter extends BaseAdapter implements Filterable { private ListoriginalData = null; private List filteredData = null; private LayoutInflater mInflater; private ItemFilter mFilter = new ItemFilter(); public SearchableAdapter(Context context, List 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 list = originalData; int count = list.size(); final ArrayList nlist = new ArrayList (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 ) 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(); }
объявить ниже код в classе адаптера
private ArrayList myList; // for loading main list private ArrayList arraylist=null; // for loading filter data
ниже кода в адаптере Конструктор
this.arraylist = new ArrayList(); this.arraylist.addAll(myList);
и ниже кода в вашем classе активности
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 updatelist = (ArrayList ) 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 (); 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 lstBkp; public List 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 (); lstBkp = new ArrayList (); //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 novaLista){ runOnUiThread(new Runnable(){ @Override public void run(){ adapterNormal.notifyDataSetChanged(); } }); }
вы можете найти собственный class адаптера списка с возможностью фильтрации с помощью изменения текста в текстовом редакторе …
создать собственный class адаптера списка с помощью функции Filterable:
private class CustomListAdapter extends BaseAdapter implements Filterable{ private LayoutInflater inflater; private ViewHolder holder; private ItemFilter mFilter = new ItemFilter(); public CustomListAdapter(List 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 list = YourObject.getYourDataList(); int count = list.size(); final ArrayList nlist = new ArrayList (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 ) 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)
, который принадлежит classу ArrayAdapter
.
Вы можете реализовать фильтр поиска в виде списка двумя способами. 1. используя searchview 2. с помощью edittext.
-
Если вы хотите использовать searchview, читайте здесь: searchview filter.
-
Если вы хотите использовать edittext, читайте ниже.
Я взял ссылку из: listview search filter android
Фрагменты кода для создания фильтра с помощью edittext.
Сначала создайте class модели MovieNames.java:
public class MovieNames { private String movieName; public MovieNames(String movieName) { this.movieName = movieName; } public String getMovieName() { return this.movieName; } }
Создать файл listview_item.xml:
Сделать class 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 arraylist; public ListViewAdapter(Context context, ArrayList 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:
Наконец, сделайте class 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 movieNamesArrayList; public static ArrayList 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); } }); } }