1

对于我的自定义适配器,我希望能够过滤 ListView 中的项目。我实现了Filterable,并创建了一个Filter。

这是我的发布结果:

@Override
protected void publishResults(CharSequence constraint, FilterResults results)
{
    MainActivity.this.filteredPetList.clear();
    MainActivity.this.filteredPetList.addAll((ArrayList<Pet>)results.values);

    notifyDataSetChanged();
}

如果我在之后检查filteredPetList

MainActivity.this.filteredPetList.addAll((ArrayList<Pet>)results.values);

,结果显示很好,但适配器不会更新视图。

任何想法我做错了什么?我可能又在做一些愚蠢的事情了。

-Edit- 在我的适配器中,我覆盖了 notifyDataSetChanged,以查看它是否实际被调用。它说:

@Override
public void notifyDataSetChanged()
{
    System.out.println("Notified...");
    super.notifyDataSetChanged();
}

每当我尝试过滤时,都会得到一个结果,notifyDataSetChanged 会被调用。我还检查了我的 filteredPetList 是否真的在过滤器之外被更改,并且确实如此。

只是视图由于某种原因没有更新......

-Edit- 添加了完整的适配器代码:

private class PetAdapter extends BaseAdapter implements Filterable
{
    private final Object lock = new Object();
    List<Row> rows;
    ArrayList<Integer> petIds;
    boolean clickable;
    PetFilter petFilter;

    public PetAdapter(ArrayList<Pet> petList, boolean clickable)
    {
        this.clickable = clickable;
        rows = new ArrayList<Row>();
        this.petIds= new ArrayList<Integer>();

        for(Pet p : petList)
        {
            rows.add(new ImageTextTextRow(LayoutInflater.from(MainActivity.this), p.getPetImageId(), p.getPetName(), p.getPetFood()));
            petIds.add(p.getPetId());
        }
    }

    @Override
    public boolean isEnabled(int position)
    {
        //Can do that certain items ARE enabled by using the position
        return clickable;
    }

    @Override
    public int getViewTypeCount()
    {
        return RowType.values().length;
    }

    @Override
    public int getItemViewType(int position)
    {
        return rows.get(position).getViewType();
    }

    @Override
    public int getCount()
    {
        return rows.size();
    }

    @Override
    public Object getItem(int position)
    {
        return rows.get(position);
    }

    @Override
    public long getItemId(int position)
    {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent)
    {
        return rows.get(position).getView(convertView);
    }

    /**
     * 
     * @param position
     * @return
     */
    public int getSelectedPetId(int position)
    {
        return petIds.get(position);
    }

    @Override
    public Filter getFilter()
    {
        if (petFilter == null)
            petFilter  = new PetFilter();

        return petFilter;
    }

    private class PetFilter extends Filter
    {
        @Override
        protected FilterResults performFiltering(CharSequence constraint)
        {
            FilterResults results = new FilterResults();

            if (MainActivity.this.filteredPetList == null)
            {
                synchronized (PetAdapter.this.lock)
                { 
                    MainActivity.this.filteredPetList = new ArrayList<Pet>(MainActivity.this.originalPetList);
                }
            }

            if (constraint == null || constraint.length() == 0)
            {
                synchronized (PetAdapter.this.lock)
                {
                    results.values = MainActivity.this.originalPetList;
                    results.count = MainActivity.this.originalPetList.size();
                }
            } 
            else
            {
                String constraintString = constraint.toString().toLowerCase(Locale.ENGLISH);

                final ArrayList<Pet> items = MainActivity.this.filteredPetList;
                final int count = items.size();
                final ArrayList<Pet> newItems = new ArrayList<Pet>(count);
                for (int i = 0; i < count; i++)
                {
                    final Pet item = items.get(i);
                    final String itemName = item.getPetName().toLowerCase(Locale.ENGLISH);

                    if (itemName.startsWith(constraintString))
                    {
                        newItems.add(item);
                    }
                    else
                    {
                        final String[] words = itemName.split(" ");
                        final int wordCount = words.length;
                        for (int k = 0; k < wordCount; k++)
                        {
                            if (words[k].startsWith(constraintString))
                            {
                                newItems.add(item);
                                break;
                            }
                        }
                    }
                }

                results.values = newItems;
                results.count = newItems.size();
            }
            return results;
        }

        @Override
        protected void publishResults(CharSequence constraint, FilterResults results)
        {
            MainActivity.this.filteredPetList.clear();
            MainActivity.this.filteredPetList.addAll((ArrayList<Pet>)results.values);

            if (results.count > 0)
                PetAdapter.this.notifyDataSetChanged();
            else
                PetAdapter.this.notifyDataSetInvalidated();
        }
    }
}

提前致谢!

特里根

4

3 回答 3

1

感谢 Luksprog,我找到了解决方案,请参阅他对我的问题的评论。我已经改变了我的适配器,现在它工作正常。我还添加了更多代码,并进行了清理,因此它与以前有点不同,但是当您阅读 Luksprog 的评论和我的代码时,应该清楚我所做的更改。

private class PetAdapter extends BaseAdapter implements Filterable
{
    private final Object lock = new Object();

    private List<Row> rows;
    private ArrayList<Integer> petIds;
    private boolean clickable;
    private ArrayList<Pet> filteredPetList;
    private PetFilter petFilter;

    public PetAdapter(boolean clickable)
    {
        this.rows = new ArrayList<Row>();
        this.petIds = new ArrayList<Integer>();
        this.clickable = clickable;
        this.filteredPetList = new ArrayList<Pet>(MainActivity.this.petList);

        createPetRows();
    }

    @Override
    public boolean isEnabled(int position)
    {
        //Can do that certain items ARE enabled/disabled by using the position
        return clickable;
    }

    @Override
    public int getViewTypeCount()
    {
        return RowType.values().length;
    }

    @Override
    public int getItemViewType(int position)
    {
        return rows.get(position).getViewType();
    }

    @Override
    public int getCount()
    {
        return rows.size();
    }

    @Override
    public Object getItem(int position)
    {
        return rows.get(position);
    }

    @Override
    public long getItemId(int position)
    {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent)
    {
        return rows.get(position).getView(convertView);
    }

    /**
     * Retrieve the petId for the selected row
     * @param position the position in the list
     * @return the petId that belongs to that row
     */
    public int getSelectedPetId(int position)
    {
        return petIds.get(position);
    }

    /**
     * Creates rows that are displayed from items in the filteredPetList
     * Also adds petIds to a List, so that the selected pet can be found
     */
    private void createPetRows()
    {
        //Clear all current data
        rows.clear();
        petIds.clear();

        for(Pet p : filteredPetList)
        {
            rows.add(new ImageTextTextRow(LayoutInflater.from(MainActivity.this), p.getPetImageId(), p.getPetName(), p.getPetFood()));
            petIds.add(p.getPetId());
        }
    }

    @Override
    public Filter getFilter()
    {
        if (petFilter == null)
            petFilter  = new PetFilter();

        return petFilter;
    }

    /**
     * Custom Filter for our PetAdapter
     * @author Bas
     *
     */
    private class PetFilter extends Filter
    {
        @Override
        protected FilterResults performFiltering(CharSequence constraint)
        {
            FilterResults results = new FilterResults();

            if (PetAdapter.this.filteredPetList == null)
            {
                synchronized (PetAdapter.this.lock)
                {
                    PetAdapter.this.filteredPetList = new ArrayList<Pet>(MainActivity.this.petList);
                }
            }

            //No constraint is sent to filter by so we're going to send back the original array
            if (constraint == null || constraint.length() == 0)
            {
                synchronized (PetAdapter.this.lock)
                {
                    results.values = MainActivity.this.petList;
                    results.count = MainActivity.this.petList.size();
                }
            } 
            else
            {
                String constraintString = constraint.toString().toLowerCase(Locale.ENGLISH);

                ArrayList<Pet> itemsToCheck = MainActivity.this.petList;

                final ArrayList<Pet> newFilteredPets = new ArrayList<Pet>(itemsToCheck.size());
                for(Pet p : itemsToCheck)
                {
                    final String petName = p.getPetName().toLowerCase(Locale.ENGLISH);
                    final String petFood = p.getPetFood().toLowerCase(Locale.ENGLISH);

                    // First match against the whole, non-splitted value
                    if (petName.startsWith(constraintString) || petFood.startsWith(constraintString))
                        newFilteredPets.add(p);
                    else
                    {
                        final String[] petNameWords = petName.split(" ");
                        final String[] petFoodWords = petFood.split(" ");
                        for (String s : petNameWords)
                        {
                            if (s.startsWith(constraintString))
                            {
                                newFilteredPets.add(p);
                                break;
                            }
                        }
                        for (String s : petFoodWords)
                        {
                            if (s.startsWith(constraintString))
                            {
                                newFilteredPets.add(p);
                                break;
                            }
                        }
                    }
                }

                //Set the result
                results.values = newFilteredPets;
                results.count = newFilteredPets.size();
            }
            return results;
        }

        @Override
        protected void publishResults(CharSequence constraint, FilterResults results)
        {
            //Add the results to our filteredPetList
            PetAdapter.this.filteredPetList.clear();
            PetAdapter.this.filteredPetList.addAll((ArrayList<Pet>)results.values);

            //Create rows for every filtered Pet
            createPetRows();

            //Notify the Adapter
            if (results.count > 0)
                PetAdapter.this.notifyDataSetChanged();
            else
                PetAdapter.this.notifyDataSetInvalidated();

            //Update the tvResults TextView with the amount of results found
            TextView tvResults = (TextView)findViewById(R.id.tvResults);

            if(results.count < MainActivity.this.petList.size())
            {
                tvResults.setText(results.count + " results found.");
                tvResults.setVisibility(View.VISIBLE);
            }
            else
            {
                tvResults.setText("");
                tvResults.setVisibility(View.GONE);
            }
        }
    }
}
于 2013-07-26T23:50:59.877 回答
0

您可能只需要从您的适配器调用 notifyDataSetChanged() 。

于 2013-07-26T17:00:09.007 回答
-1

我会给你我的工作自定义过滤器代码:

 public class NaamFilter extends Filter {

    @Override
    protected FilterResults performFiltering(CharSequence constraint) {
        FillArray();
        FilterResults results = new FilterResults();

            List<String> filtered = new ArrayList<String>();
            for (String naam : namenarraylist) {
                if(naam.toLowerCase().contains(constraint.toString().toLowerCase())) {
                    filtered.add(naam);
                }
            }
            results.values = filtered;
            results.count = filtered.size();
            return results;
    }

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

    }

}
于 2013-07-26T16:21:47.553 回答