Tabs SherlockListFragment中的SearchView

Tabs SherlockListFragment中的SearchView,tabs,actionbarsherlock,android-viewpager,android-listfragment,searchview,Tabs,Actionbarsherlock,Android Viewpager,Android Listfragment,Searchview,我在SherlockListFragment中使用SearchView时遇到一些问题。有一个自定义的ArrayAdapter和一个listview,其中每个项目包含一个图像和两个文本视图。在我为我的ListFragment应用SearchView之前,一切都很好。搜索图标是可展开的,我还可以在搜索栏中输入单词 问题 自定义适配器现在可以过滤listview,但当我从可展开的searchview中删除最后一个字母或关闭searchview时,应用程序崩溃 我已经附上了我的ArrayAdapter类

我在SherlockListFragment中使用SearchView时遇到一些问题。有一个自定义的ArrayAdapter和一个listview,其中每个项目包含一个图像和两个文本视图。在我为我的ListFragment应用SearchView之前,一切都很好。搜索图标是可展开的,我还可以在搜索栏中输入单词

问题

自定义适配器现在可以过滤listview,但当我从可展开的searchview中删除最后一个字母或关闭searchview时,应用程序崩溃

我已经附上了我的ArrayAdapter类,以及下面我的SherlockListFragment

带有筛选器类的自定义阵列适配器

 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;
    }

}
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);
}
 }

有人能帮我吗?thx

当Sherlock中的
搜索视图
展开时,它会将
文本视图
组件设置为
,您可以从源代码中看到它:

 @Override
public void onActionViewExpanded() {
    if (mExpandedInActionView) return;

    mExpandedInActionView = true;
    mCollapsedImeOptions = mQueryTextView.getImeOptions();
    mQueryTextView.setImeOptions(mCollapsedImeOptions | EditorInfo.IME_FLAG_NO_FULLSCREEN);
    mQueryTextView.setText("");
    setIconified(false);
}
这就是过滤器返回原始数据的原因。相反,与android.widget.SearchView相比,当action视图也折叠时,它不会将查询设置为“”。长话短说,您需要用“”省略筛选(除非需要),并且还要检查在执行筛选时是否使
列表视图无效,因为您尚未发布筛选实现

编辑:筛选listview的示例

私有类MyFilter扩展了过滤器{

@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
    if (results!=null && results.count > 0) {
        items = (ArrayList<Data>) results.values;
        notifyDataSetChanged();

    }
}

@Override
protected FilterResults performFiltering(CharSequence constraint) {
    constraint = constraint.toString().toLowerCase();
    items = mOriginalData;
    if (constraint.length() == 0 || constraint.equals("")) {
        FilterResults original = new FilterResults();
        original.count = items.size();
        original.values = items;
        return original;
    } else {
        List<Data> filtered = new ArrayList<Data>();
        for (Data l : items) {
            if ( SOME CONDITION TO FILTER ){ // YOU NEED TO CHANGE THIS
             filtered.add(l);
            }
        }
        FilterResults newFilterResults = new FilterResults();
        newFilterResults.count = filtered.size();
        newFilterResults.values = filtered;
        return newFilterResults;
    }
}

在这里查看我的答案谢谢你的回答。请查看编辑后的版本。这一次,它不会返回原始列表,而是显示“No shop”,即使我键入了与列表中文本匹配的内容。更奇怪的是,我发现只有在键入包名时,它才不会显示“No shop”,但列表将保持不变。知道为什么吗?哦,你的意思是我不能在onQueryTextChange中仅使用mAdapter.getFilter?你能提供一些示例或给我一些提示,说明如何根据我上面提供的ShopListAdapter方法在适配器中筛选项吗?提前感谢我刚刚上传了完整的java代码。那么,我应该把priv放在哪里ate类MyFilter扩展了Filter?在我的情况下,我应该用什么替换“items”呢?谢谢如果你想保持类私有,请将它与适配器放在同一个类文件中。因此,私有类MyFilter和筛选器类都必须放在我的适配器类ISIT?和“items”中引用列表,对吗?以及如何调用onQueryTextChange()中的筛选器类?谢谢。
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
    if (results!=null && results.count > 0) {
        items = (ArrayList<Data>) results.values;
        notifyDataSetChanged();

    }
}

@Override
protected FilterResults performFiltering(CharSequence constraint) {
    constraint = constraint.toString().toLowerCase();
    items = mOriginalData;
    if (constraint.length() == 0 || constraint.equals("")) {
        FilterResults original = new FilterResults();
        original.count = items.size();
        original.values = items;
        return original;
    } else {
        List<Data> filtered = new ArrayList<Data>();
        for (Data l : items) {
            if ( SOME CONDITION TO FILTER ){ // YOU NEED TO CHANGE THIS
             filtered.add(l);
            }
        }
        FilterResults newFilterResults = new FilterResults();
        newFilterResults.count = filtered.size();
        newFilterResults.values = filtered;
        return newFilterResults;
    }
}
@Override
public Filter getFilter() {
    if (mFilter == null) {
        mFilter = new MyFilter();
    }
    return mFilter;
}