使用 Baseadapter 过滤 ListView 过滤文本而不是图像

Posted

技术标签:

【中文标题】使用 Baseadapter 过滤 ListView 过滤文本而不是图像【英文标题】:Filtering a ListView with Baseadapter filters text not images 【发布时间】:2012-06-01 15:24:10 【问题描述】:

在较早的问题上取得了一些进展。现在有一个新问题。 GridView 中的文本显示了正确的结果。但是,图像与列表开头的图像相同。

例如:如果我搜索“Sidd”,它会显示三个结果,但照片仍然以“A”开头的用户开始。为清楚起见,附上截图。

这是 BaseAdapter 代码:

public class TagFriendsAdapter extends BaseAdapter implements Filterable 

    List<String> arrayListNames;
    List<String> mOriginalNames;

    List<String> arrayPictures;
    List<String> mOriginalPictures;

    Activity activity;
    String[] fetFriendID;
    String[] fetFriendName;
    String[] fetFriendPicture;

    LayoutInflater inflater = null;
    ImageLoader imageLoader;

    TagFriendsAdapter(Activity a, String[] stringUID, String[] stringName, String[] stringPicture,
            ArrayList<String> arrayName, ArrayList<String> arrayPicture) 

        activity = a;
        fetFriendID = stringUID;
        fetFriendName = stringName;
        fetFriendPicture = stringPicture;

        this.arrayListNames = arrayName;
        this.arrayPictures = arrayPicture;

        inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        imageLoader = new ImageLoader(activity.getApplicationContext());
    

    public int getCount() 
        return arrayListNames.size();
    

    public Object getItem(int position) 
        return position;
    

    public long getItemId(int position) 
        return position;
    

    @Override
    public void notifyDataSetChanged() 
        super.notifyDataSetChanged();
    

    public View getView(final int position, View convertView, ViewGroup parent) 
        View vi = convertView;
        if(convertView == null)
            vi = inflater.inflate(R.layout.friends_grid_items, null);

        ImageView imgProfilePicture = (ImageView)vi.findViewById(R.id.imgProfilePicture);
        TextView txtUserName = (TextView)vi.findViewById(R.id.txtUserName);

        txtUserName.setText(arrayListNames.get(position));

        if (arrayPictures.get(position) != null)
            imageLoader.DisplayImage(arrayPictures.get(position), imgProfilePicture);
        
        else if (arrayPictures.get(position) == null) 
            imgProfilePicture.setVisibility(View.GONE);
        

        return vi;
    

    @Override
    public Filter getFilter() 

        Filter filter = new Filter() 

            @SuppressWarnings("unchecked")
            @Override
            protected void publishResults(CharSequence constraint, FilterResults results) 

                arrayListNames = (List<String>) results.values;
                notifyDataSetChanged();
            

            @Override
            protected FilterResults performFiltering(CharSequence constraint) 

                FilterResults results = new FilterResults();
                ArrayList<String> FilteredArrayNames = new ArrayList<String>();

                if (mOriginalNames == null && mOriginalPictures == null)    
                    mOriginalNames = new ArrayList<String>(arrayListNames);
                    mOriginalPictures = new ArrayList<String>(arrayPictures);
                
                if (constraint == null || constraint.length() == 0) 
                    results.count = mOriginalNames.size();
                    results.values = mOriginalNames;
                 else 
                    constraint = constraint.toString().toLowerCase();
                    for (int i = 0; i < mOriginalNames.size(); i++) 
                        String dataNames = mOriginalNames.get(i);
                        if (dataNames.toLowerCase().startsWith(constraint.toString()))  
                            FilteredArrayNames.add(dataNames);
                        
                    

                    results.count = FilteredArrayNames.size();
                    System.out.println(results.count);

                    results.values = FilteredArrayNames;
                    Log.e("VALUES", results.values.toString());
                

                return results;
            
        ;

        return filter;
    


还有截图:

【问题讨论】:

忘记 +1 其他用户的答案是因为他们试图提供解决方案并努力阅读我的烂摊子。 ;-) 【参考方案1】:

首先重构您的代码。创建一个将姓名、图片和其他朋友数据保存在一起的类。

class Friend 
    public String name;
    public String picture;
    ... /* more members and access methods*/
;

然后相应地修改您的适配器和过滤代码。

FilterResults 应该包含ArrayList&lt;Friend&gt;,即Friend 对象的列表,而不仅仅是名称。

在适配器中,替换

List&lt;String&gt; arrayListNames;List&lt;String&gt; arrayPictures;

List&lt;Friend&gt; friendsList;

更改getView 方法以访问friendsList 对象列表中的数据。

进行这些更改后,代码看起来会更好,工作也会更好。

更新:

确保您的适配器的 getItem 方法返回一个 Friend 对象

public Object getItem(int position) 
    return mFriendsList.get(position);

【讨论】:

您能否在您发布的答案中添加更多细节?我已经尝试了前两个问题,但没有一个有效。理想情况下,我希望花更多时间尝试调试这两个解决方案中的任何一个,但您的建议似乎更有意义。例如,在您提出的第一个建议中,重构代码位,您的意思是将我解析 JSON 结果的整个部分移至此类? 也许我可以重新发布我的整个活动,再次将数据发送到这个适配器。如果有帮助的话。 从 JSON 数据创建一个 Friend 对象列表。在循环中,创建一个新的Friend 对象并将其添加到ArrayList。每个Friend 对象将代表一个朋友信息。 有没有一个可行的例子可以借鉴一些逻辑?从我的角度来看,你的回答有点模糊。同样,如果我有时间,我会研究并找出答案,但不幸的是,我没有。很抱歉,但一个例子就是时间的需要。 我认为没有其他方法可以用于过滤您的情况。由于您的数据有 2 个不同的列表...并且您只能在 performFiltering 方法中返回 1 个结果列表。因此,您必须制作一个对象(包含名称和图片)才能使其工作。【参考方案2】:

问题是因为您在根据edittext输入过滤数组时没有更新图片名称列表,您还需要更新它们,

我已尝试修改您的代码,请检查此

    public static List<String> temparrayPictures; 
    public static List<String> temparrayListNames; 
    public class TagFriendsAdapter extends BaseAdapter implements Filterable  

        List<String> arrayListNames; 
        List<String> arrayPictures; 

        Activity activity; 
        String[] fetFriendID; 
        String[] fetFriendName; 
        String[] fetFriendPicture; 

        LayoutInflater inflater = null; 
        ImageLoader imageLoader; 

        TagFriendsAdapter(Activity a, String[] stringUID, String[] stringName, String[] stringPicture, 
                ArrayList<String> arrayName, ArrayList<String> arrayPicture)  

            activity = a; 
            fetFriendID = stringUID; 
            fetFriendName = stringName; 
            fetFriendPicture = stringPicture; 

            this.arrayListNames = arrayName; 
            this.arrayPictures = arrayPicture; 
            temparrayPictures = arrayPicture;
            temparrayListNames = arrayName;

            inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
            imageLoader = new ImageLoader(activity.getApplicationContext()); 
         

        public int getCount()  
            return temparrayListNames.size(); 
         

        public Object getItem(int position)  
            return position; 
         

        public long getItemId(int position)  
            return position; 
         

        @Override 
        public void notifyDataSetChanged()  
            super.notifyDataSetChanged(); 
         

        public View getView(final int position, View convertView, ViewGroup parent)  
            View vi = convertView; 
            if(convertView == null) 
                vi = inflater.inflate(R.layout.friends_grid_items, null); 

            ImageView imgProfilePicture = (ImageView)vi.findViewById(R.id.imgProfilePicture); 
            TextView txtUserName = (TextView)vi.findViewById(R.id.txtUserName); 

            txtUserName.setText(temparrayListNames.get(position)); 

            if (temparrayPictures.get(position) != null) 
                imageLoader.DisplayImage(temparrayPictures.get(position), imgProfilePicture); 
             
            else if (temparrayPictures.get(position) == null)  
                imgProfilePicture.setVisibility(View.GONE); 
             

            return vi; 
         

        @Override 
        public Filter getFilter()  

            Filter filter = new Filter()  

                @SuppressWarnings("unchecked") 
                @Override 
                protected void publishResults(CharSequence constraint, FilterResults results)  

                    notifyDataSetChanged(); 
                 

                @Override 
                protected FilterResults performFiltering(CharSequence constraint)  

                    FilterResults results = new FilterResults();
                    temparrayPictures.clear();
                    temparrayListNames.clear();

                    if (temparrayListNames == null && temparrayPictures == null)     
                        temparrayListNames = new ArrayList<String>(arrayListNames); 
                        temparrayPictures = new ArrayList<String>(arrayPictures); 
                     
                    if (constraint == null || constraint.length() == 0)  
                        results.count = arrayListNames.size(); 
                        results.values = arrayListNames; 

                        temparrayPictures = arrayPictures;
                        temparrayListNames = arrayListNames;
                     else  
                        constraint = constraint.toString().toLowerCase(); 
                        for (int i = 0; i < mOriginalNames.size(); i++)  
                            String dataNames = arrayName.get(i); 
                            String picNames =  arrayPicture.get(i);
                            if (dataNames.toLowerCase().startsWith(constraint.toString()))   
                                temparrayPictures.add(picNames);
                                temparrayListNames.add(dataNames);
                             
                         

                        results.count = temparrayListNames.size(); 
                        System.out.println(results.count); 

                        results.values = temparrayListNames; 
                        Log.e("VALUES", results.values.toString()); 
                     

                    return results; 
                 
            ; 

            return filter; 
         

     

【讨论】:

虽然,它需要更多的内存用于临时列表,但无论如何对少数要求都有好处。 mOriginalNames 应该是 arrayName【参考方案3】:

试试这个:

public class TagFriendsAdapter extends BaseAdapter implements Filterable


    List<String> arrayListNames;
    List<String> mOriginalNames;

    List<String> arrayPictures;
    List<String> mOriginalPictures;

    Activity activity;
    String[] fetFriendID;
    String[] fetFriendName;
    String[] fetFriendPicture;

    LayoutInflater inflater = null;
    ImageLoader imageLoader;

    private Hashtable<String, String> picturesMap = new Hashtable<String, String>();

    public void setNamesAndPictures(List<String> arrayListNames, List<String> arrayPictures) 
        for(int i = 0; i < arrayListNames.size(); i++)
            picturesMap.put(arrayListNames.get(i), arrayPictures.get(i));
        

        this.arrayListNames = arrayListNames;
    

    TagFriendsAdapter(Activity a, String[] stringUID, String[] stringName, String[] stringPicture,
            ArrayList<String> arrayName, ArrayList<String> arrayPicture) 

        activity = a;
        fetFriendID = stringUID;
        fetFriendName = stringName;
        fetFriendPicture = stringPicture;

        this.arrayListNames = arrayName;
        this.arrayPictures = arrayPicture;

        inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        imageLoader = new ImageLoader(activity.getApplicationContext());
    

    @Override
    public int getCount() 
        return arrayListNames.size();
    

    @Override
    public Object getItem(int position) 
        return position;
    

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

    @Override
    public void notifyDataSetChanged() 
        super.notifyDataSetChanged();
    

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) 
        View vi = convertView;
        if(convertView == null)
            vi = inflater.inflate(R.layout.friends_grid_items, null);

        ImageView imgProfilePicture = (ImageView) vi.findViewById(R.id.imgProfilePicture);
        TextView txtUserName = (TextView) vi.findViewById(R.id.txtUserName);

        txtUserName.setText(arrayListNames.get(position));

        String url = picturesMap.get(arrayListNames.get(position));
        if(url != null)
            imageLoader.DisplayImage(url, imgProfilePicture);
        
        else if(arrayPictures.get(position) == null)
            imgProfilePicture.setVisibility(View.GONE);
        

        return vi;
    

    @Override
    public Filter getFilter() 

        Filter filter = new Filter() 

            @SuppressWarnings("unchecked")
            @Override
            protected void publishResults(CharSequence constraint, FilterResults results) 

                arrayListNames = (List<String>) results.values;
                notifyDataSetChanged();
            

            @Override
            protected FilterResults performFiltering(CharSequence constraint) 

                FilterResults results = new FilterResults();
                ArrayList<String> FilteredArrayNames = new ArrayList<String>();

                if(mOriginalNames == null && mOriginalPictures == null)
                    mOriginalNames = new ArrayList<String>(arrayListNames);
                    mOriginalPictures = new ArrayList<String>(arrayPictures);
                
                if(constraint == null || constraint.length() == 0)
                    results.count = mOriginalNames.size();
                    results.values = mOriginalNames;
                
                else
                    constraint = constraint.toString().toLowerCase();
                    for(int i = 0; i < mOriginalNames.size(); i++)
                        String dataNames = mOriginalNames.get(i);
                        if(dataNames.toLowerCase().startsWith(constraint.toString()))
                            FilteredArrayNames.add(dataNames);
                        
                    

                    results.count = FilteredArrayNames.size();
                    System.out.println(results.count);

                    results.values = FilteredArrayNames;
                    Log.e("VALUES", results.values.toString());
                

                return results;
            
        ;

        return filter;
    


【讨论】:

对不起,FilterResults 类是什么?您的意思是发送到此适配器的源? 我的“arrayPictures”从未改变这一事实是问题的根源。我的过滤是在用户名上完成的。如何将名称与图片的位置联系起来是我怀疑的问题。 @SiddharthLele 创建一个用用户名存储 URL 的哈希。然后,当您应用名称时,您将可以访问图像 URL @SiddharthLele 是的!如果您获得的记录少于 10,000 条,它将完成这项工作,如果您获得的记录更多,则使用数据库 嗯...你能给我举个例子,或者建议对我自己的代码进行更改吗?我之前在启动线程时添加了原始活动,如果您愿意,可以将其添加回来。【参考方案4】:

@MKJParekh 做得很好!总结一下他的实现:

    在类的开头声明一个临时对象列表,以反映用于每个项目的传入数据(每个项目 1 个对象)。 在performFiltering()中设置空字符串和空字符串的条件,并且如果约束匹配相应对象的字符串值,则将该对象添加到临时列表中。这样你只有一个“过滤”的对象列表。 对于getCount()getItem()getView() 等方法,使用您的临时列表中的数据,而不是您的数据源(就像您通常那样)。否则,您每次都会加载所有项目,因为每次过滤后都会不恰当地调用notifyDataSetChanged()

【讨论】:

以上是关于使用 Baseadapter 过滤 ListView 过滤文本而不是图像的主要内容,如果未能解决你的问题,请参考以下文章

使用 Baseadapter 过滤 ListView 过滤文本而不是图像

BaseAdapter Listview过滤Android

如何在 BaseAdapter 上实现 getFilter?

在 ListView [mvvm] 中过滤数据

java 为listvie实现基础适配器

Android中BaseAdapter使用基础点