0

我在我的 SherlockListFragment 中使用 SearchView 时遇到了一些麻烦。有一个自定义 ArrayAdapter 和一个列表视图,其中每个项目包含一个图像和两个 TextView。在我为我的 ListFragment 应用 SearchView 之前,一切都运行良好。搜索图标是可扩展的,我还可以在搜索栏中输入单词。

问题

自定义适配器现在能够过滤列表视图,但是当我从可扩展搜索视图中删除最后一个字母或关闭搜索视图时,应用程序崩溃了。

我在下面附加了我的 ArrayAdapter 类以及我的 SherlockListFragment。

具有过滤器类的自定义 ArrayAdapter

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

}

我的 ListFragment 类

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

日志文件

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)

谁能帮我 ?谢谢

4

1 回答 1

1

SearchViewin Sherlock 展开时,它将TextView组件设置为"",您可以从源代码中看到它:

 @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它不会在操作视图也折叠时将查询设置为“”。长话短说,您需要使用“”省略过滤(除非需要),并且还要检查您是否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;
    }
}

};

在您的适配器中:

@Override
public Filter getFilter() {
    if (mFilter == null) {
        mFilter = new MyFilter();
    }
    return mFilter;
}
于 2013-08-17T13:01:22.577 回答