Страница 1 из 1

Поиск в SimpleAdapter'е

Добавлено: 06 апр 2014, 23:00
Fb89
Всем привет! Есть ListView (картинка и текст), данные взяты из SimpleAdapter'а. Вопрос: как можно нормально применить метод setFilterText(String str) к ListView, а то выкидывает NullPointerException, другими словами, как осуществить поиск через SearchView в таком ListView? С ArrayAdapter'ом никаких проблем нет.

Re: Поиск в SimpleAdapter'е

Добавлено: 07 апр 2014, 06:48
Foenix
поиск осуществим простым перебором. Ваш NPE может быть из-за ошибки в цикле. Без кода ничего не скажешь.

Re: Поиск в SimpleAdapter'е

Добавлено: 07 апр 2014, 09:57
Fb89

Код: Выделить всё

package com.example.searchingtest;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.SearchView;
import android.widget.SearchView.OnQueryTextListener;
import android.widget.SimpleAdapter;
import android.widget.TextView;

public class MainActivity extends Activity implements OnQueryTextListener {
	 
private SearchView search;
private ListView listView;

SimpleAdapter sAdapter;
ArrayList<Map<String, Object>> data;
Map<String, Object> m;	
final String ATTRIBUTE_NAME_IMAGE = "image";
final String ATTRIBUTE_NAME_TEXT = "text";
String[] from = { ATTRIBUTE_NAME_IMAGE, ATTRIBUTE_NAME_TEXT};
int[] to = { R.id.iv, R.id.tv};
 
private final String[] stateList = {"Karnataka","Kerala","Tamil Nadu","Maharashtra",
"Goa","Madhya Pradesh","Andhra Pradesh"};
 
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		data = new ArrayList<Map<String, Object>>();
	    for (int i=0; i<stateList.length;i++) {
	    	m = new HashMap<String, Object>();
	    	
	    	m.put(ATTRIBUTE_NAME_IMAGE, R.drawable.ic_launcher);
		    m.put(ATTRIBUTE_NAME_TEXT, stateList[i]);
		    data.add(m);
		}
	    
	        sAdapter = new SimpleAdapter(this, data, R.layout.item, from, to);

		listView = (ListView) findViewById(R.id.list_view);
		listView.setAdapter(sAdapter);
		listView.setTextFilterEnabled(true);
		//listView.setFilterText("a");	 
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
	    MenuInflater inflater = getMenuInflater();
	    inflater.inflate(R.menu.main, menu);

	    search = (SearchView)menu.findItem(R.id.search).getActionView();
	    search.setIconifiedByDefault(false);
	    search.setOnQueryTextListener(this);	  		 
	    search.setQueryHint("State Name");
	    return true;
	}
	
	@Override
	public boolean onQueryTextChange(String newText) {
		if (TextUtils.isEmpty(newText)) {
		listView.clearTextFilter();
		} else {
		listView.setFilterText(newText.toString());
		}
		return true;
	}
	 
	@Override
		public boolean onQueryTextSubmit(String query) {
		return false;
	}		
}
Картинки для каждого пункта разные, это я для примера одну и ту же загружаю.
Exception выскакивает при изменении текста в SearchView, но так же его можно получить просто раскомментировав метод listView.setFilterText("a");

Re: Поиск в SimpleAdapter'е

Добавлено: 07 апр 2014, 10:31
Foenix
выкидывает NullPointerException
это тоже нужно прилагать.

Re: Поиск в SimpleAdapter'е

Добавлено: 07 апр 2014, 11:02
Fb89

Код: Выделить всё

04-07 08:48:21.026: W/Filter(779): An exception occured during performFiltering()!
04-07 08:48:21.026: W/Filter(779): java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
04-07 08:48:21.026: W/Filter(779): 	at android.widget.SimpleAdapter$SimpleFilter.performFiltering(SimpleAdapter.java:352)
04-07 08:48:21.026: W/Filter(779): 	at android.widget.Filter$RequestHandler.handleMessage(Filter.java:234)
04-07 08:48:21.026: W/Filter(779): 	at android.os.Handler.dispatchMessage(Handler.java:99)
04-07 08:48:21.026: W/Filter(779): 	at android.os.Looper.loop(Looper.java:137)
04-07 08:48:21.026: W/Filter(779): 	at android.os.HandlerThread.run(HandlerThread.java:60)
04-07 08:48:21.276: W/EGL_emulation(779): eglSurfaceAttrib not implemented
04-07 08:48:21.308: D/AndroidRuntime(779): Shutting down VM
04-07 08:48:21.308: W/dalvikvm(779): threadid=1: thread exiting with uncaught exception (group=0x40a71930)
04-07 08:48:21.356: E/AndroidRuntime(779): FATAL EXCEPTION: main
04-07 08:48:21.356: E/AndroidRuntime(779): java.lang.NullPointerException
04-07 08:48:21.356: E/AndroidRuntime(779): 	at android.widget.SimpleAdapter.getCount(SimpleAdapter.java:93)
04-07 08:48:21.356: E/AndroidRuntime(779): 	at android.widget.AdapterView.checkFocus(AdapterView.java:712)
04-07 08:48:21.356: E/AndroidRuntime(779): 	at android.widget.AdapterView$AdapterDataSetObserver.onInvalidated(AdapterView.java:835)
04-07 08:48:21.356: E/AndroidRuntime(779): 	at android.widget.AbsListView$AdapterDataSetObserver.onInvalidated(AbsListView.java:5966)
04-07 08:48:21.356: E/AndroidRuntime(779): 	at android.database.DataSetObservable.notifyInvalidated(DataSetObservable.java:50)
04-07 08:48:21.356: E/AndroidRuntime(779): 	at android.widget.BaseAdapter.notifyDataSetInvalidated(BaseAdapter.java:59)
04-07 08:48:21.356: E/AndroidRuntime(779): 	at android.widget.SimpleAdapter$SimpleFilter.publishResults(SimpleAdapter.java:383)
04-07 08:48:21.356: E/AndroidRuntime(779): 	at android.widget.Filter$ResultsHandler.handleMessage(Filter.java:282)
04-07 08:48:21.356: E/AndroidRuntime(779): 	at android.os.Handler.dispatchMessage(Handler.java:99)
04-07 08:48:21.356: E/AndroidRuntime(779): 	at android.os.Looper.loop(Looper.java:137)
04-07 08:48:21.356: E/AndroidRuntime(779): 	at android.app.ActivityThread.main(ActivityThread.java:5041)
04-07 08:48:21.356: E/AndroidRuntime(779): 	at java.lang.reflect.Method.invokeNative(Native Method)
04-07 08:48:21.356: E/AndroidRuntime(779): 	at java.lang.reflect.Method.invoke(Method.java:511)
04-07 08:48:21.356: E/AndroidRuntime(779): 	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
04-07 08:48:21.356: E/AndroidRuntime(779): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
04-07 08:48:21.356: E/AndroidRuntime(779): 	at dalvik.system.NativeStart.main(Native Method)

Re: Поиск в SimpleAdapter'е

Добавлено: 07 апр 2014, 11:26
Foenix
это не весь

Re: Поиск в SimpleAdapter'е

Добавлено: 07 апр 2014, 11:50
Fb89
Обновил

Re: Поиск в SimpleAdapter'е

Добавлено: 07 апр 2014, 12:50
Foenix
да не весь же!
Ищите строку Caused by: (по причине)
далее в строках ищите адрес в своей программе, щелкайте туда два раза и предъявите код

Re: Поиск в SimpleAdapter'е

Добавлено: 07 апр 2014, 12:59
Fb89
В том-то и дело, что весь! :D Насколько я понимаю из первых строк:

Код: Выделить всё

04-07 08:48:21.026: W/Filter(779): An exception occured during performFiltering()!
04-07 08:48:21.026: W/Filter(779): java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
происходит попытка привести ID рисунка к текстовому формату и применить к нему фильтр. А как указать принудительно, по какому именно полю фильтровать - не знаю. В каком месте кода происходит ошибка и так могу сказать - в месте применения фильтра

Re: Поиск в SimpleAdapter'е

Добавлено: 07 апр 2014, 13:38
Foenix
тебе нужно в этих строках искать АДРЕС В СВОЕЙ ПРОГРАММЕ, т.е. имя пакета, модуль, метод, строка такая-то. Они будут после строки Caused by;

Re: Поиск в SimpleAdapter'е

Добавлено: 07 апр 2014, 14:01
Fb89
Я это понимаю, но говорю как есть: caused by отсутствует. Если есть желание - посмотри, проект по ссылке http://www.ex.ua/337094252539

Re: Поиск в SimpleAdapter'е

Добавлено: 07 апр 2014, 15:43
Foenix
скорее всего у тебя стандартный поисковик и адаптер не хочет работать с твоим мапом Map<String, Object> m;
второй объект у тебя целое, вот оно и птается его преобразовать в String и не может.
придется тебе делать кастомный адаптер и реализовать все эти поиски вручную) Все равно тебе возможностей стандартного может не хватить.

Re: Поиск в SimpleAdapter'е

Добавлено: 08 апр 2014, 10:03
Fb89
Да, тоже думал придётся заморочиться с кастомным адаптером - так и вышло. Вот код, может кому-то пригодится:

Код: Выделить всё

	public class MyAdapter extends BaseAdapter implements Filterable
	{
		public ArrayList<Map<String, Object>> data;//полученные значения
		public ArrayList<Map<String, Object>> mOriginalValues; // Original Values
		LayoutInflater inflater;
		
		public MyAdapter(Context context, ArrayList<Map<String, Object>> data) {
	        this.data = data;
	        mOriginalValues=new ArrayList<Map<String, Object>>(data);
	        inflater = LayoutInflater.from(context);
	    }
		
		@Override
	    public int getCount() {
	        return data.size();
	    }

	    @Override
	    public Object getItem(int position) {
	        return data.get(position);
	    }
	    //выдаёт реальное значение  ID, независимо от смещения при фильтрации
	    @Override
	    public long getItemId(int position) {
	    	int ID=mOriginalValues.indexOf(getItem(position));
	    	return ID;
	    }
		
		private class ViewHolder {
		    ImageView ivImg;   
			TextView tvText;
		    }

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {

			ViewHolder holder = null;
			if (convertView == null) {
				holder = new ViewHolder();
				convertView = inflater.inflate(R.layout.item, null);
				holder.tvText = (TextView) convertView.findViewById(R.id.tvText);
				holder.ivImg = (ImageView) convertView.findViewById(R.id.ivImg);
				convertView.setTag(holder);
		        } else {
		            holder = (ViewHolder) convertView.getTag();
		        }
		        Map<String, Object> m=data.get(position);
	            String str = (String)m.get(ATTRIBUTE_NAME_TEXT);
	            int img=(Integer)m.get(ATTRIBUTE_NAME_IMAGE);
		        holder.tvText.setText(str);
		        holder.ivImg.setImageResource(img);
		        return convertView;
		    }
		
	    @Override
	    public Filter getFilter() {
	    	Filter filter = new Filter() {

	    		@SuppressWarnings("unchecked")
	    		@Override
	    		protected void publishResults(CharSequence constraint,FilterResults results) {

	    			data = (ArrayList<Map<String, Object>>) results.values;
	    			notifyDataSetChanged();
	    			}

	    		@Override
	    		protected FilterResults performFiltering(CharSequence constraint) {
	    			FilterResults results = new FilterResults();
	    			ArrayList<Map<String, Object>> FilteredArrList=new ArrayList<Map<String,Object>>();

	    			if (constraint == null || constraint.length() == 0) { 
	    				results.count = mOriginalValues.size();
	    				results.values = mOriginalValues;
	    				} else {
	    					constraint = constraint.toString().toLowerCase();
	    					for (int i = 0; i < mOriginalValues.size(); i++) {
	    						Map<String, Object> m=mOriginalValues.get(i);
		                        String str = (String)m.get("text");
		                        //если в конкретном элементе оригинальных значений присутствует искомый набор символов, то добавляем этот эл-т в FilteredArrList
		                        if (str.toLowerCase().contains(constraint.toString())) {
		                            FilteredArrList.add(m);
		                            }
		                        }
	    					results.count = FilteredArrList.size();
		                    results.values = FilteredArrList;
		                    }
	    		return results;
	    		}
	    	};
	    	return filter;
		}		 
	}