Android listview using ViewHolder
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();
}
Solution 4:
You can try this
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;
}
}