Android:在ListView中通过SearchView搜索

时间:2016-06-23 12:28:13

标签: android listview android-fragments filter searchview

我是Android的新手,也是StackOverflow的新手:)

我目前正在编写应用程序,它在ListView中显示文章。

我的目标是,我想要ListView中的搜索/过滤选项。 我创建了一个Fragment,其中显示了输入的SearchView和填充了文章的ListView

我的问题是,当我在SearchView中输入一封信时,我的应用因IndexOutOfBounceException而崩溃。

java.lang.IndexOutOfBoundsException: Invalid index 2, size is 2
at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255)
at java.util.ArrayList.get(ArrayList.java:308)
at klinar.kronlachner.binder.app.Article_List_Adapter.getView(Article_List_Adapter.java:62)
at android.widget.AbsListView.obtainView(AbsListView.java:2347)
at android.widget.ListView.measureHeightOfChildren(ListView.java:1270)
at android.widget.ListView.onMeasure(ListView.java:1182)
at android.view.View.measure(View.java:17586)

我在我的ArticleAdapter中创建了一个自定义过滤器,用于比较文章标题是否包含SearchView的输入。

以下是适配器类的代码:

class Article_List_Adapter extends ArrayAdapter<Article> implements Filterable {
public static final String TAG = "List_Adapter Test";
public List<Article> articles;
CustomFilter filter;

public Article_List_Adapter(Context _c, int textViewResourceId, List<Article> articles) {
    super(_c, textViewResourceId, articles);
    this.articles = articles;
}

public class ViewHolder {
    ImageView article_icon;
    TextView articleTitle;
    TextView articleCategory;
    TextView articleDate;
    TextView articleAuthor;
}

@Override
public View getView(int _position, View _convertView, ViewGroup _parent) {
    View view = _convertView;
    ViewHolder viewHolder;

    if (view == null) {
        LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        view = inflater.inflate(R.layout.article_list_row, null);
        viewHolder = new ViewHolder();
        viewHolder.article_icon = (ImageView) view.findViewById(R.id.article_category_icon);
        viewHolder.articleTitle = (TextView) view.findViewById(R.id.article_title);
        viewHolder.articleCategory = (TextView) view.findViewById(R.id.article_category);
        viewHolder.articleDate = (TextView) view.findViewById(R.id.article_date);
        viewHolder.articleAuthor = (TextView) view.findViewById(R.id.article_author);
        view.setTag(viewHolder);
    } else {
        viewHolder = (ViewHolder) _convertView.getTag();
    }

    //Find the article to work with
    //Article currentArticle = getItem(_position);
    Article currentArticle = articles.get(_position);

    //fill the Article_View
    switch (currentArticle.getCategory()) {
        case "Kernel": {
            viewHolder.article_icon.setImageResource(R.drawable.ic_list_letter_k);
        }
        break;
        case "Security": {
            viewHolder.article_icon.setImageResource(R.drawable.ic_list_letter_s);
        }
        break;
        default: {
            viewHolder.article_icon.setImageResource(R.drawable.ic_list_letter_s);
        }
    }
    viewHolder.articleTitle.setText(currentArticle.getTitle());
    viewHolder.articleCategory.setText(currentArticle.getCategory());
    viewHolder.articleDate.setText(currentArticle.getDate());
    viewHolder.articleAuthor.setText(currentArticle.getAuthor());
    return view;
}

public Filter getFilter() {
    if (filter == null) {
        filter = new CustomFilter();
    }
    return filter;
}

class CustomFilter extends Filter {
    @Override
    protected FilterResults performFiltering(CharSequence _constraint) {
        FilterResults results = new FilterResults();
        ArrayList<Article> article_list = (ArrayList<Article>) articles;
        Log.e(TAG, "articles size: "+article_list.size());
        ArrayList<Article> tempList = new ArrayList<>();
        if (_constraint != null && articles != null) {
            for (final Article a : article_list) {
                if (a.getTitle().toLowerCase().contains(_constraint.toString())) {
                    tempList.add(a);
                }
            }
            Log.e(TAG, "tempList size: "+tempList.size());
            results.values = tempList;
            results.count = tempList.size();
        }
        return results;

    }

    @Override
    protected void publishResults(CharSequence constraint, FilterResults results) {
        articles = (ArrayList<Article>) results.values;
        if (results.count > 0) {
            notifyDataSetChanged();
        } else {
            notifyDataSetInvalidated();
        }
    }
}
}

这里是My Fragment,它显示了SearchView和ListView:

public class SearchFragment extends Fragment {
private ListView articleListView;
private List<Article> articles;
private SearchView inputSearch;
private ArrayAdapter<Article> article_list_adapter;

public SearchFragment() {
    // Required empty public constructor
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

    View view = inflater.inflate(R.layout.fragment_search, container, false);
    articles = MainActivity.getInstance().getArticleList();

    articleListView = (ListView) view.findViewById(R.id.search_list_view);
    inputSearch = (SearchView) view.findViewById(R.id.inputSearch);

    //Create and Set Adapter for ListView
    article_list_adapter = new Article_List_Adapter(getActivity(), R.layout.article_list_row, articles);
    articleListView.setAdapter(article_list_adapter);

    //Set Property for SearchView
    inputSearch.setQueryHint("Search");

    //SEARCH
    inputSearch.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
        @Override
        public boolean onQueryTextSubmit(String query) {
            return false;
        }

        @Override
        public boolean onQueryTextChange(String query) {
            article_list_adapter.getFilter().filter(query);
            return false;
        }
    });
    return view;
}
}    

我希望我没有忘记任何事情。 THX!

P.S。这是我的第一篇文章

1 个答案:

答案 0 :(得分:0)

这里有错误。

@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
    articles = (ArrayList<Article>) results.values;
    if (results.count > 0) {
        notifyDataSetChanged();
    } else {
        notifyDataSetInvalidated();
    }
}

您的类从基类扩展,并将List放在基础构造函数中,因此您更新articles引用基类中的引用。因此,ListView获取放在基类构造函数中的List的项目数 要解决此问题,您需要覆盖getItemsCount方法(请参阅Android文档中的正确方法名称。