ListView ArrayAdapter过滤 - 重复项目

时间:2011-10-13 12:03:45

标签: android filter custom-adapter

我尝试使用自定义适配器过滤listview。当我开始在edittext上输入时,应该过滤列表视图。下面是适配器的代码。自定义对象具有重写的方法toString,它返回facebook用户的名称。我没有覆盖ArrayAdapter方法getItem,添加或删除。

public class FacebookFriendsAdapter extends ArrayAdapter<FacebookUser> {
    private Activity activity;
    public ImageLoader imageLoader;
    private HashMap<String, Integer> alphaIndexer;
    private String[] sections = new String[0];
    private boolean enableSections;

    public FacebookFriendsAdapter(Context context, int textViewResourceId,ArrayList<FacebookUser> newItems) {
        super(context, textViewResourceId, newItems);
        imageLoader = new ImageLoader(context.getApplicationContext());
    }

    public static class ViewHolder {
        public TextView text;
        public ImageView image;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View rowView = convertView;
        FacebookUser fcbu = getItem(position);

        if (convertView == null) {
            LayoutInflater vi = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            rowView = vi.inflate(R.layout.facebook_friendslist_row, null);
            final ViewHolder holder = new ViewHolder();
            holder.text = (TextView) rowView.findViewById(R.id.facebook_rowFriendName);
            holder.image = (ImageView) rowView.findViewById(R.id.facebookRowUserFoto);
            rowView.setTag(holder);
        } else {
            rowView = convertView;
        }
        ViewHolder holder = (ViewHolder) rowView.getTag();

        String imageurl = "http://graph.facebook.com/" + fcbu.getId()+ "/picture";
        holder.text.setText(fcbu.getName());
        holder.image.setTag(imageurl);
        imageLoader.DisplayImage(imageurl, holder.image);
        return rowView;
    }
}

在包含EditText的活动中,我创建了一个TextWatcher,如:

private TextWatcher filterTextWatcher = new TextWatcher() {

        public void afterTextChanged(Editable s) {

        }

        public void beforeTextChanged(CharSequence s, int start, int count,
                int after) {
        }

        public void onTextChanged(CharSequence s, int start, int before,
                int count) {
            facebookAdapter.getFilter().filter(s);
        }
    };

一切正常,期望在过滤列表后,过滤的项目会重复。

A会理解可能导致这种情况的任何想法。 感谢

1 个答案:

答案 0 :(得分:5)

由于How to write a custom filter for ListView with ArrayAdapter,我解决了这个问题。

以下是改编的自定义适配器

public class FBAdapter extends ArrayAdapter<FacebookUser> {
    public ImageLoader imageLoader;
    private ArrayList<FacebookUser> items;
    private ArrayList<FacebookUser> originalItems = new ArrayList<FacebookUser>();
    private FBAdapterFilter filter;
    private final Object mLock = new Object();

    public FBAdapter(Context context, int textViewResourceId,
            ArrayList<FacebookUser> newItems) {
        super(context, textViewResourceId, newItems);
        imageLoader = new ImageLoader(context);
        items = newItems;
        cloneItems(newItems);
    }

    protected void cloneItems(ArrayList<FacebookUser> items) {
        for (Iterator iterator = items.iterator(); iterator.hasNext();) {
            FacebookUser gi = (FacebookUser) iterator.next();
            originalItems.add(gi);
        }
    }

    @Override
    public int getCount() {
        synchronized (mLock) {
            return items != null ? items.size() : 0;
        }
    }

    @Override
    public FacebookUser getItem(int item) {
        FacebookUser gi = null;
        synchronized (mLock) {
            gi = items != null ? items.get(item) : null;

        }
        return gi;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View rowView = convertView;
        final FacebookUser fcbu = getItem(position);

        if (convertView == null) {
            LayoutInflater vi = (LayoutInflater) getContext().getSystemService(
                    Context.LAYOUT_INFLATER_SERVICE);
            rowView = vi.inflate(R.layout.facebook_friendslist_row, null);
            final ViewHolder holder = new ViewHolder();
            holder.text = (TextView) rowView
                    .findViewById(R.id.facebook_rowFriendName);
            holder.image = (ImageView) rowView
                    .findViewById(R.id.facebookRowUserFoto);
            holder.checkbox = (CheckBox) rowView
                    .findViewById(R.id.chkInviteFacebookFriend);
            holder.checkbox
                    .setOnCheckedChangeListener(new OnCheckedChangeListener() {
                        @Override
                        public void onCheckedChanged(CompoundButton buttonView,
                                boolean isChecked) {
                            FacebookUser element = (FacebookUser) holder.checkbox
                                    .getTag();
                            element.setSelected(buttonView.isChecked());
                            holder.checkbox.setTag(element);
                        }
                    });
            rowView.setTag(holder);
            holder.checkbox.setTag(fcbu);

        } else {
            rowView = convertView;
            ((ViewHolder) rowView.getTag()).checkbox.setTag(fcbu);

        }
        ViewHolder holder = (ViewHolder) rowView.getTag();

        String imageurl = "http://graph.facebook.com/" + fcbu.getId()
                + "/picture";
        holder.text.setText(fcbu.getName());
        holder.image.setTag(imageurl);
        holder.checkbox.setChecked(fcbu.isSelected());

        imageLoader.DisplayImage(imageurl, holder.image);
        return rowView;
    }

    /**
     * Implementing the Filterable interface.
     */
    public Filter getFilter() {
        if (filter == null) {
            filter = new FBAdapterFilter();
        }
        return filter;
    }

    /**
     * Custom Filter implementation for the items adapter.
     * 
     */
    private class FBAdapterFilter extends Filter {
        protected FilterResults performFiltering(CharSequence prefix) {
            // Initiate our results object
            FilterResults results = new FilterResults();

            // No prefix is sent to filter by so we're going to send back the
            // original array
            if (prefix == null || prefix.length() == 0) {
                synchronized (mLock) {
                    results.values = originalItems;
                    results.count = originalItems.size();
                }
            } else {
                synchronized (mLock) {
                    // Compare lower case strings
                    String prefixString = prefix.toString().toLowerCase();
                    final ArrayList<FacebookUser> filteredItems = new ArrayList<FacebookUser>();
                    // Local to here so we're not changing actual array
                    final ArrayList<FacebookUser> localItems = new ArrayList<FacebookUser>();
                    localItems.addAll(originalItems);
                    final int count = localItems.size();

                    for (int i = 0; i < count; i++) {
                        final FacebookUser item = localItems.get(i);
                        final String itemName = item.getName().toString()
                                .toLowerCase();

                        // First match against the whole, non-splitted value
                        if (itemName.startsWith(prefixString)) {
                            filteredItems.add(item);
                        } else {
                        } /*
                         * This is option and taken from the source of
                         * ArrayAdapter final String[] words =
                         * itemName.split(" "); final int wordCount =
                         * words.length;
                         * 
                         * for (int k = 0; k < wordCount; k++) { if
                         * (words[k].startsWith(prefixString)) {
                         * newItems.add(item); break; } } }
                         */
                    }

                    // Set and return
                    results.values = filteredItems;
                    results.count = filteredItems.size();
                }// end synchronized
            }

            return results;
        }

        @SuppressWarnings("unchecked")
        @Override
        protected void publishResults(CharSequence prefix, FilterResults results) {
            // noinspection unchecked
            synchronized (mLock) {
                final ArrayList<FacebookUser> localItems = (ArrayList<FacebookUser>) results.values;
                notifyDataSetChanged();
                clear();
                // Add the items back in
                for (Iterator iterator = localItems.iterator(); iterator
                        .hasNext();) {
                    FacebookUser gi = (FacebookUser) iterator.next();
                    add(gi);
                }
            }// end synchronized
        }
    }

    public ArrayList<FacebookUser> getSelectedItems() {
        ArrayList<FacebookUser> result = new ArrayList<FacebookUser>();
        for (FacebookUser friend : items) {
            if (friend.isSelected())
                result.add(friend);
        }
        return result;
    }
}

我还在AsyncTask上加载了facebook朋友,所以我改变了这种方式,因此在postExecute中填充了适配器:

@Override
        protected void onPostExecute(ArrayList<FacebookUser> result) {

            if (result != null && result.size() > 0) {
                facebookAdapter = new FBAdapter(
                        InviteFriendsFromFacebookActivity.this,
                        R.layout.facebook_friendslist_row, result);
                facebookListView.setAdapter(facebookAdapter);
                facebookListView.setVisibility(View.VISIBLE);
                facebookAdapter.notifyDataSetChanged();
            }

        }

现在问题已经消失。感谢