【问题标题】:Android: searching Via SearchView in ListViewAndroid:在 ListView 中通过 SearchView 搜索
【发布时间】:2016-06-23 12:28:12
【问题描述】:

我对 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();
        }
    }
}
}

这是我的片段,它显示了 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;
}
}    

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

附:这是我的第一篇文章

【问题讨论】:

标签: android listview android-fragments filter searchview


【解决方案1】:

这里是错误。

@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 文档中的正确方法名称。

【讨论】:

  • 所以你的意思是我需要添加:getCount(){} getItem(int pos), getItemId(int post){}, 方法?我在哪里使用它们
  • 是的,如果它有这样的方法(对不起,我不记得了)。而在这个方法中你需要返回articles.size()
  • 如果您对引用数据类型了解得不好。你需要阅读它,最好在 C/C++ 中尝试一下
  • 什么时候调用这个方法?或者这到底是为了什么?
  • ListView可以了解适配器中存在多少项
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-11
  • 1970-01-01
  • 2012-10-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多