Android listview using ViewHolder

36,600

Solution 1

Change your code at below. I think you're missing that.

public class AlphabeticalAdapter extends ArrayAdapter<String> {
    int layoutResourceId;
    private final Context context;
    private List<String> data;
    private List<String> tags;
    private ProgressDialog mProgressDialog;
    private ImageView downloadImageButton;

    public AlphabeticalAdapter(Context context, int resource, List<String> data) {
        super(context, resource, data);
        this.layoutResourceId = resource;
        this.context = context;
        this.data = data;
        tags = new ArrayList<String>();
        int size = data.size();
        for (int i = 0; i < size; i++) {
            tags.add("tag");
        }
    }

    static class ViewHolder {
        ImageView downloadImageButton;
        TextView catlogTitle;
        ImageView icon;
        int position;
    }

    public View getView(final int position, View convertView, ViewGroup parent) {

        // View rowView = convertView;
        final ViewHolder viewHolder;

        if (convertView == null) {
            LayoutInflater inflater = (LayoutInflater) context
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            // convertView = inflater.inflate(R.layout.catalogslist_single_row,
            // parent, false);
            viewHolder = new ViewHolder();
            viewHolder.position = position;
            viewHolder.downloadImageButton
                    .setOnClickListener(new OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            System.out.println("DOWNLOAD PRESSED");
                            viewHolder.downloadImageButton.setTag("downloaded");
                            tags.add(position, "downloaded");
                        }
                    });
            convertView.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) convertView.getTag();
        }

        viewHolder.catlogTitle.setText(data.get(position));
        viewHolder.catlogTitle.setTypeface(regularDin);
        viewHolder.icon.setImageResource(R.drawable.cata);

        if (tags.get(position) == "downloaded") {
            downloadImageButton.setImageResource(R.drawable.icon_ok);
        } else {
            downloadImageButton.setImageResource(R.drawable.icon_download);
        }

        viewHolder.position = position;
        return convertView;
    } // close getView
}

Solution 2

There are as many convertViews as many row visible in the same time in your ListView (the system reuses it). So you actually have 5 convertView, and because of that you have 5 ImageView for the icons. The problem is that you use those ImageView's tag to store the "downloaded" information. That is 5 state, and that is why you see every fifth row downloaded while you scroll in the list.

I guess now you see that it won't work. You need to store the downloaded state for every item, so you have to change the underlying List<String> to List<ListItem>, where ListItem can store the downloaded state for the actual row.

After that, all you have to do is to update the convertView's ImageView (in getView()) to show the correct icon.

Solution 3

Change your code like this. Add null check with convertView before your try block.

    final MenuItem   menuItem = getItem(position);
    View view = convertView;
    final ViewHolder viewHolder;

if (convertView == null) {

    LayoutInflater inflater;

        inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        view = inflater.inflate(R.layout.menu_item, parent, false);
        viewHolder = new ViewHolder();
//      viewHolder.half = (TextView) view.findViewById(R.id.half);
        viewHolder.name = (TextView) view.findViewById(R.id.name);
        viewHolder.description = (TextView) view.findViewById(R.id.description);
        viewHolder.price = (TextView) view.findViewById(R.id.price);
        viewHolder.add = (Button) view.findViewById(R.id.add);
        viewHolder.selectedView = view.findViewById(R.id.selectedView);
        viewHolder.remove = (Button) view.findViewById(R.id.remove);
        viewHolder.total = (TextView) view.findViewById(R.id.itemTotal);
        viewHolder.quantity = (TextView) view.findViewById(R.id.quantity);
        view.setTag(viewHolder);
}else{
    viewHolder= (ViewHolder)convertView.getTag(); 
}
Share:
36,600
Mark
Author by

Mark

Updated on July 09, 2022

Comments

  • Mark
    Mark almost 2 years

    I have a problem. I'm attempting to change an icon in my listview after it has been clicked. It works correctly although are not modified only the clicked icons but also those who are not displayed. For example if I click the icon in the first item of the listview, also the fifth icon changes. This behaviour is repeated for all the following items (every five items of the listview). This is my getView method:

       public class AlphabeticalAdapter extends ArrayAdapter<String>
       {
           int layoutResourceId; 
           private final Context context;
           private List<String> data;
           private ProgressDialog mProgressDialog;
           private ImageView downloadImageButton;
    
    
           public AlphabeticalAdapter(Context context, int resource, List<String> data){
               super(context, resource, data);
               this.layoutResourceId = resource;
               this.context = context;
               this.data = data;    
           }
    
           public View getView(int position, View convertView, ViewGroup parent) {
    
              // View rowView = convertView;
               final ViewHolder viewHolder;
    
               if (convertView == null) {
    
                   LayoutInflater inflater = (LayoutInflater) context
                            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    
    
                   convertView  = inflater.inflate(R.layout.catalogslist_single_row, parent, false);
    
               viewHolder = new ViewHolder();
    
               viewHolder.catlogTitle=(TextView)convertView.findViewById(R.id.txtTitle);
               viewHolder.icon=(ImageView)convertView.findViewById(R.id.imageView2); 
               viewHolder.downloadImageButton=(ImageView)convertView.findViewById(R.id.downloadImageButton);
    
               //downloadImageButton = (ImageView)rowView.findViewById(R.id.downloadImageButton);
    
               viewHolder.position = position;
    
    
               viewHolder.downloadImageButton.setOnClickListener(new OnClickListener() {
                   @Override  
                   public void onClick(View v) {
                         System.out.println("DOWNLOAD PRESSED");
    
                         viewHolder.downloadImageButton = (ImageView)v.findViewById(R.id.downloadImageButton);
                         viewHolder.downloadImageButton.setImageResource(R.drawable.icon_ok);
                         viewHolder.downloadImageButton.setTag("downloaded");
                         //rowView.setTag("downloaded");
    
    
                     }
                 });
    
    
    
               convertView.setTag(viewHolder);
    
               }
    
               else{
                   viewHolder= (ViewHolder)convertView.getTag(); 
               }
    
               viewHolder.catlogTitle.setText(data.get(position));
               viewHolder.catlogTitle.setTypeface(regularDin);
               viewHolder.icon.setImageResource(R.drawable.cata);
    
    
               if(viewHolder.downloadImageButton.getTag() == "downloaded"){
                 downloadImageButton = (ImageView)convertView.findViewById(R.id.downloadImageButton);
                 downloadImageButton.setImageResource(R.drawable.icon_ok);
               }
               else{
                   downloadImageButton = (ImageView)convertView.findViewById(R.id.downloadImageButton);
                     downloadImageButton.setImageResource(R.drawable.icon_download);
               }
    
    
               viewHolder.position = position;
    
            return convertView;
    
           } //close getView 
    

    ...

    And this is my ViewHolder class:

          static class ViewHolder{
           ImageView downloadImageButton;
           TextView catlogTitle;
           ImageView icon;
           int position;
       }