web-dev-qa-db-fra.com

Listview Android utilisant ViewHolder

J'ai un problème. J'essaie de changer une icône dans ma liste après avoir cliqué dessus. Il fonctionne correctement bien que ne soient pas modifiées uniquement les icônes cliquées, mais également celles qui ne sont pas affichées. Par exemple, si je clique sur l'icône dans le premier élément de la liste, la cinquième icône change également. Ce comportement est répété pour tous les éléments suivants (tous les cinq éléments de la vue liste). Voici ma méthode getView:

   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 

...

Et voici ma classe ViewHolder:

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

Changez votre code en bas. Je pense que vous manquez ça.

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
}
10
Divyang Metalia

Il y a autant de convertViews que de rangées visibles en même temps dans votre ListView (le système les réutilise). Donc, vous avez réellement 5 convertView, et à cause de cela, vous avez 5 ImageView pour les icônes. Le problème est que vous utilisez ces balises ImageView pour stocker les informations "téléchargées". C’est l’état 5, et c’est pourquoi vous voyez toutes les cinq lignes téléchargées lorsque vous faites défiler la liste.

Je suppose que maintenant, vous voyez que cela ne fonctionnera pas. Vous devez stocker l'état téléchargé pour chaque élément. Vous devez donc modifier le List<String> sous-jacent en List<ListItem>, où ListItem peut stocker l'état téléchargé pour la ligne réelle.

Après cela, tout ce que vous avez à faire est de mettre à jour la variable convertView de ImageView (dans getView()) pour afficher la bonne icône.

5
kupsef

Tu peux essayer ça

public class CustomArrayAdapter extends ArrayAdapter {

// declare your custom list with type;
private List<YourModelClass> allData = new ArrayList<YourModelClass>();

public CustomArrayAdapter(@NonNull Context context, List<YourModelClass> allData) {
    super(context, R.layout.your_layout, allData); // add your_layout.xml
    this.allData = allData;
}

class ViewHolder {
    TextView name, phone; // declare your your_layout.xml view type
}

@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
    LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    ViewHolder holder = new ViewHolder();
    if (convertView == null) {

        convertView = inflater.inflate(R.layout.your_layout, parent, false); // inflate your_layout.xml

        //initialize your your_layout.xml view
        holder.name = convertView.findViewById(R.id.tv_item_name);
        holder.phone = convertView.findViewById(R.id.tv_item_phone);

        convertView.setTag(holder);
    } else {
        holder = (ViewHolder) convertView.getTag();
    }

    //set value into your_layout.xml
    holder.name.setText(allData.get(position).getName());
    holder.phone.setText(allData.get(position).getNumber());

    return convertView;
}

}

1
user10398830
public class AndroidListViewActivity extends ListActivity 
{
   private ListView listView;
   private String names[] = {
        "HV CAPACITOR",
        "LV CAPACITORCSS",

         };

private String desc[] = {
        "The Powerful Hypter Text Markup Language 5",
        "Cascading Style Sheets",

};


private Integer imageid[] = {
        R.drawable.hv_capacitor,
        R.drawable.lv_capacitor,

};

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
   // setContentView(R.layout.capacitor_layout);
    // storing string resources into Array
    String[] product_name = getResources().getStringArray(R.array.product_name);
    // Binding Array to ListAdapter
    this.setListAdapter(new ArrayAdapter<String>(this, R.layout.list_item, R.id.label, product_name));

    ListView lv = getListView();

    // listening to single list item on click

    lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        public void onItemClick(AdapterView<?> parent, View view,
                                int position, long id) {

            // selected item
            String product = ((TextView) view).getText().toString();

            // Launching new Activity on selecting single List Item
            Intent i = new Intent(getApplicationContext(), SingleListItem.class);
            // sending data to new activity
            i.putExtra("product", product);
            startActivity(i);

        }
    });


    CapacitorList capacitorList = new CapacitorList(this, names, desc, imageid);
    listView = (ListView) findViewById(R.id.listView);
    listView.setAdapter(capacitorList);

    listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {

        // Launching new Activity on selecting single List Item
        Intent i = new Intent(getApplicationContext(), CapacitorList.class);
        // sending data to new activity

       // startActivity(i);

        @Override
        public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
            Toast.makeText(getApplicationContext(), "You Clicked " + names[i], Toast.LENGTH_SHORT).show();
        }
    });

}

    @Override
    public boolean onCreateOptionsMenu (Menu menu){
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected (MenuItem item){
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);


    }
}
0
shilpa Todakar

Changez votre code comme ça. Ajoutez un contrôle nul avec convertView avant votre bloc try.

    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(); 
}
0
Rakesh