I have some troubles using SearchView in my SherlockListFragment.There is a custom ArrayAdapter and a listview which contains one image and two TextViews for each item. Everything works well until I applied SearchView for my ListFragment. The search icon is expandable and I'm also able to enter words into the search bar.
PROBLEM
The custom adapter is able to filter the listview now, but when I delete the last letter from the expandable searchview, or close the searchview, the app crashed.
I have attached my ArrayAdapter class, as well as, my SherlockListFragment below.
Custom ArrayAdapter with Filter Class
public static class ShopListAdapter extends ArrayAdapter<ShopEntry>
{
private final LayoutInflater mInflater;
private List<ShopEntry> filteredData;
private List<ShopEntry> originalData;
public ShopListAdapter(Context context, List<ShopEntry> filteredData)
{
super(context, android.R.layout.simple_list_item_2, filteredData);
mInflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.filteredData = filteredData;
}
public void setData(List<ShopEntry> data)
{
clear();
if(data != null)
{
for(ShopEntry ShopEntry : data)
{
add(ShopEntry);
}
}
filteredData = data;
originalData = data;
}
@Override
public int getCount()
{
return filteredData.size();
}
@Override
public ShopEntry getItem(int pos)
{
return filteredData.get(pos);
}
/**
* Populate new items in the list.
*/
@Override
public View getView(int position, View convertView, ViewGroup parent)
{
View view;
if(convertView == null)
{
view = mInflater.inflate(R.layout.specific_shop_list_item,
parent, false);
}
else
{
view = convertView;
}
ShopEntry item = filteredData.get(position);
String url = item.getImg();
((SmartImageView) view.findViewById(R.id.shopImg)).setImageUrl(url);
((TextView) view.findViewById(R.id.shopType)).setText(item
.getShopName());
view.setBackgroundColor(0xff1e8e8);
return view;
}
private class MyFilter extends Filter
{
@SuppressWarnings("unchecked" )
@Override
protected void publishResults(CharSequence constraint,
FilterResults results)
{
if(results != null && results.count > 0)
{
filteredData = (ArrayList<ShopEntry>) results.values;
notifyDataSetChanged();
}
}
@Override
protected FilterResults performFiltering(CharSequence constraint)
{
constraint = constraint.toString();
filteredData = originalData;
if(constraint.length() == 0 || constraint.equals(""))
{
FilterResults original = new FilterResults();
original.count = filteredData.size();
original.values = filteredData;
return original;
}
else
{
List<ShopEntry> filtered = new ArrayList<ShopEntry>();
for(ShopEntry l : filteredData)
{
if(l.getShopName().contains(constraint))
{ // YOU NEED TO CHANGE THIS
filtered.add(l);
Log.d("filter", "filter " + constraint + " "
+ l.getShopName().toString());
}
}
FilterResults newFilterResults = new FilterResults();
newFilterResults.count = filtered.size();
newFilterResults.values = filtered;
return newFilterResults;
}
}
}
MyFilter mFilter;
@Override
public Filter getFilter()
{
if(mFilter == null)
{
mFilter = new MyFilter();
}
return mFilter;
}
}
My ListFragment Class
public class ShopListFragment extends SherlockListFragment implements
LoaderManager.LoaderCallbacks<List<ShopEntry>>, OnQueryTextListener
{
List<ShopEntry> shopEntry = new ArrayList<ShopEntry>();
// This is the Adapter being used to display the list's data.
ShopListAdapter mAdapter;
SearchView searchView;
// If non-null, this is the current filter the user has provided.
String mCurFilter = "";
OnQueryTextListenerCompat mOnQueryTextListenerCompat;
@Override
public void onActivityCreated(Bundle savedInstanceState)
{
super.onActivityCreated(savedInstanceState);
// Give some text to display if there is no data. In a real
// application this would come from a resource.
setEmptyText("No Such Shop");
// We have a menu item to show in action bar.
setHasOptionsMenu(true);
// Create an empty adapter we will use to display the loaded data.
mAdapter = new ShopListAdapter(getActivity(), shopEntry);
setListAdapter(mAdapter);
// Start out with a progress indicator.
setListShown(false);
// Prepare the loader. Either re-connect with an existing one,
// or start a new one.
getLoaderManager().initLoader(0, null, this);
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
{
// Place an action bar item for searching.
// super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.menu_with_search, menu);
MenuItem item = menu.findItem(R.id.action_search);
searchView = new SearchView(getSherlockActivity().getSupportActionBar()
.getThemedContext());
searchView.setQueryHint(getString(R.string.search_hint));
searchView.setOnQueryTextListener(this);
int currentapiVersion = android.os.Build.VERSION.SDK_INT;
if(currentapiVersion >= android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH)
{
item.setOnActionExpandListener(new OnActionExpandListener()
{
@Override
public boolean onMenuItemActionCollapse(MenuItem item)
{
searchView.onActionViewCollapsed();
searchView.setQuery(null, true);
searchView.clearFocus();
return true; // Return true to collapse action view
}
@Override
public boolean onMenuItemActionExpand(MenuItem item)
{
// TODO Auto-generated method stub
return true;
}
});
}
else
{
// do something for phones running an SDK before froyo
searchView.setOnCloseListener(new OnCloseListener()
{
@Override
public boolean onClose()
{
searchView.onActionViewCollapsed();
searchView.setQuery(null, true);
searchView.clearFocus();
return false;
}
});
}
item.setActionView(searchView);
super.onCreateOptionsMenu(menu, inflater);
}
@Override
public boolean onQueryTextChange(String newText)
{ // called when the action bar search text has changed. Update
// the search filter, and restart the loader to do a new query
// with this filter.
String newFilter = !TextUtils.isEmpty(newText) ? newText : null;
// Don't do anything if the filter hasn't actually changed.
// Prevents restarting the loader when restoring state.
if(mCurFilter == null && newFilter == null)
{
return true;
}
if(mCurFilter != null && mCurFilter.equals(newFilter))
{
return true;
}
mCurFilter = newFilter;
mAdapter.getFilter().filter(mCurFilter.toString());
getLoaderManager().restartLoader(0, null, this);
return true;
}
@Override
public boolean onQueryTextSubmit(String query)
{
// TODO Auto-generated method stub
return true;
}
@Override
public Loader<List<ShopEntry>> onCreateLoader(int id, Bundle args)
{
// This is called when a new Loader needs to be created. This
// sample only has one Loader with no arguments, so it is simple.
return new ShopListLoader(getActivity());
}
@Override
public void onLoadFinished(Loader<List<ShopEntry>> loader,
List<ShopEntry> data)
{
// Set the new data in the adapter.
mAdapter.setData(data);
// The list should now be shown.
if(isResumed())
{
setListShown(true);
}
else
{
setListShownNoAnimation(true);
}
}
@Override
public void onLoaderReset(Loader<List<ShopEntry>> loader)
{
// Clear the data in the adapter.
mAdapter.setData(null);
}
}
Log File
08-20 01:44:44.549: E/AndroidRuntime(4246): at android.text.SpannableStringBuilder.sendTextChanged(SpannableStringBuilder.java:962)
08-20 01:44:44.549: E/AndroidRuntime(4246): at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:496)
08-20 01:44:44.549: E/AndroidRuntime(4246): at android.text.SpannableStringBuilder.delete(SpannableStringBuilder.java:212)
08-20 01:44:44.549: E/AndroidRuntime(4246): at android.text.SpannableStringBuilder.delete(SpannableStringBuilder.java:30)
08-20 01:44:44.549: E/AndroidRuntime(4246): at android.text.method.BaseKeyListener.backspaceOrForwardDelete(BaseKeyListener.java:94)
08-20 01:44:44.549: E/AndroidRuntime(4246): at android.text.method.BaseKeyListener.backspace(BaseKeyListener.java:49)
08-20 01:44:44.549: E/AndroidRuntime(4246): at android.text.method.BaseKeyListener.onKeyDown(BaseKeyListener.java:155)
08-20 01:44:44.549: E/AndroidRuntime(4246): at android.text.method.QwertyKeyListener.onKeyDown(QwertyKeyListener.java:356)
08-20 01:44:44.549: E/AndroidRuntime(4246): at android.text.method.TextKeyListener.onKeyDown(TextKeyListener.java:136)
08-20 01:44:44.549: E/AndroidRuntime(4246): at android.widget.TextView.doKeyDown(TextView.java:5385)
08-20 01:44:44.549: E/AndroidRuntime(4246): at android.widget.TextView.onKeyDown(TextView.java:5204)
08-20 01:44:44.549: E/AndroidRuntime(4246): at android.widget.AutoCompleteTextView.onKeyDown(AutoCompleteTextView.java:716)
08-20 01:44:44.549: E/AndroidRuntime(4246): at android.view.KeyEvent.dispatch(KeyEvent.java:2609)
08-20 01:44:44.549: E/AndroidRuntime(4246): at android.view.View.dispatchKeyEvent(View.java:7205)
08-20 01:44:44.549: E/AndroidRuntime(4246): at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1359)
08-20 01:44:44.549: E/AndroidRuntime(4246): at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1359)
08-20 01:44:44.549: E/AndroidRuntime(4246): at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1359)
08-20 01:44:44.549: E/AndroidRuntime(4246): at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1359)
08-20 01:44:44.549: E/AndroidRuntime(4246): at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1359)
08-20 01:44:44.549: E/AndroidRuntime(4246): at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1359)
08-20 01:44:44.549: E/AndroidRuntime(4246): at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1359)
08-20 01:44:44.549: E/AndroidRuntime(4246): at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1359)
08-20 01:44:44.549: E/AndroidRuntime(4246): at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1359)
08-20 01:44:44.549: E/AndroidRuntime(4246): at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1359)
08-20 01:44:44.549: E/AndroidRuntime(4246): at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchKeyEvent(PhoneWindow.java:1920)
08-20 01:44:44.549: E/AndroidRuntime(4246): at com.android.internal.policy.impl.PhoneWindow.superDispatchKeyEvent(PhoneWindow.java:1395)
08-20 01:44:44.549: E/AndroidRuntime(4246): at android.app.Activity.dispatchKeyEvent(Activity.java:2370)
08-20 01:44:44.549: E/AndroidRuntime(4246): at com.actionbarsherlock.app.SherlockFragmentActivity.dispatchKeyEvent(SherlockFragmentActivity.java:121)
08-20 01:44:44.549: E/AndroidRuntime(4246): at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:1847)
08-20 01:44:44.549: E/AndroidRuntime(4246): at android.view.ViewRootImpl.deliverKeyEventPostIme(ViewRootImpl.java:3701)
08-20 01:44:44.549: E/AndroidRuntime(4246): at android.view.ViewRootImpl.handleImeFinishedEvent(ViewRootImpl.java:3651)
08-20 01:44:44.549: E/AndroidRuntime(4246): at android.view.ViewRootImpl$ViewRootHandler.handleMessage(ViewRootImpl.java:2818)
08-20 01:44:44.549: E/AndroidRuntime(4246): at android.os.Handler.dispatchMessage(Handler.java:99)
08-20 01:44:44.549: E/AndroidRuntime(4246): at android.os.Looper.loop(Looper.java:137)
08-20 01:44:44.549: E/AndroidRuntime(4246): at android.app.ActivityThread.main(ActivityThread.java:5041)
08-20 01:44:44.549: E/AndroidRuntime(4246): at java.lang.reflect.Method.invokeNative(Native Method)
08-20 01:44:44.549: E/AndroidRuntime(4246): at java.lang.reflect.Method.invoke(Method.java:511)
08-20 01:44:44.549: E/AndroidRuntime(4246): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
08-20 01:44:44.549: E/AndroidRuntime(4246): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
08-20 01:44:44.549: E/AndroidRuntime(4246): at dalvik.system.NativeStart.main(Native Method)
Can anyone help me ? thx