Reputation: 467
There are lots of questions here with the same title. I still couldn't find a solution. That's why I create a new one. I have a navigation drawer and ListView inside of it. I have two custom views for items on this ListView: header and normal. I give the views for each item by considering their positions, but when I scroll it up and down, the views mix randomly. I kept my variables on a ViewHolder. It couldn't be a solution. My adapter below:
public class NavDrawerListAdapter extends BaseAdapter {
private Context context;
private ArrayList<NavDrawerItem> navDrawerItems;
public NavDrawerListAdapter(Context context, ArrayList<NavDrawerItem> navDrawerItems) {
this.context = context;
this.navDrawerItems = navDrawerItems;
}
@Override
public int getCount() {
return navDrawerItems.size();
}
@Override
public Object getItem(int position) {
return navDrawerItems.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
private static class ViewHolder {
public ImageView icon;
public TextView title, count;
}
@Override
public int getViewTypeCount() {
return 2;
}
@Override
public int getItemViewType(int position) {
return position % 2;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
ViewHolder holder = new ViewHolder();
if (row == null) {
LayoutInflater mInflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
if (navDrawerItems.get(position).getType().equals("header")) {
row = mInflater.inflate(R.layout.drawer_list_item_header, null, false);
} else {
row = mInflater.inflate(R.layout.drawer_list_item, null, false);
}
} else {
holder = (ViewHolder) row.getTag();
}
holder.icon = (ImageView) row.findViewById(R.id.icon);
holder.title = (TextView) row.findViewById(R.id.title);
holder.count = (TextView) row.findViewById(R.id.counter);
holder.icon.setImageResource(navDrawerItems.get(position).getIcon());
holder.title.setText(navDrawerItems.get(position).getTitle());
if (navDrawerItems.get(position).getCounterVisibility()) {
holder.count.setText(navDrawerItems.get(position).getCount());
} else {
holder.count.setVisibility(View.GONE);
}
row.setTag(holder);
return row;
}
}
Upvotes: 3
Views: 5616
Reputation: 539
I have same issue when scroll quickly it alternate the vales of some item to others, just like background color of some items if changes randomly. I solved this issue by searching a lot and find exact solution is just adding these two methods in your adapter if you are using ViewHolder in your adapter
@Override
public int getViewTypeCount() {
return getCount();
}
@Override
public int getItemViewType(int position) {
return position;
}
Upvotes: 9
Reputation: 495
I agree with kaushik's answer but convertView needs to hold viewHolder
not position
, i have made changes see code..
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
holder = new ViewHolder();
LayoutInflater mInflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
if (navDrawerItems.get(position).getType().equals("header")) {
convertView = mInflater.inflate(R.layout.drawer_list_item_header, null, false);
} else {
convertView = mInflater.inflate(R.layout.drawer_list_item, null, false);
}
holder.icon = (ImageView) convertView.findViewById(R.id.icon);
holder.title = (TextView) convertView.findViewById(R.id.title);
holder.count = (TextView) convertView.findViewById(R.id.counter);
convertView.setTag(holder); //as holder will be loaded at second iteration
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.icon.setImageResource(navDrawerItems.get(position).getIcon());
holder.title.setText(navDrawerItems.get(position).getTitle());
if (navDrawerItems.get(position).getCounterVisibility()) {
holder.count.setText(navDrawerItems.get(position).getCount());
} else {
holder.count.setVisibility(View.GONE);
}
return convertView;
}
Hope it helps!...
Upvotes: 0
Reputation: 6162
Your ListView's
scrolling is laggy because
you are creating ViewHolder's object everytime while you scroll that ListView. So, your ViewHolder is useless.
try this code
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
LayoutInflater mInflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
if (navDrawerItems.get(position).getType().equals("header")) {
convertView = mInflater.inflate(R.layout.drawer_list_item_header, null, false);
holder = new ViewHolder();
holder.icon = (ImageView) convertView.findViewById(R.id.icon);
holder.title = (TextView) convertView.findViewById(R.id.title);
holder.count = (TextView) convertView.findViewById(R.id.counter);
} else {
convertView = mInflater.inflate(R.layout.drawer_list_item, null, false);
holder = new ViewHolder();
holder.icon = (ImageView) convertView.findViewById(R.id.icon);
holder.title = (TextView) convertView.findViewById(R.id.title);
holder.count = (TextView) convertView.findViewById(R.id.counter);
}
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.icon.setImageResource(navDrawerItems.get(position).getIcon());
holder.title.setText(navDrawerItems.get(position).getTitle());
if (navDrawerItems.get(position).getCounterVisibility()) {
holder.count.setText(navDrawerItems.get(position).getCount());
} else {
holder.count.setVisibility(View.GONE);
}
return convertView;
}
Upvotes: 1
Reputation: 25028
They wont mix if you override getViewTypeCount()
and getItemViewType()
in your adapter.
Once you do that, you are guaranteed that the the convertView
provided is of the appropriate type.
My ListView has two types of views. How to manage?
Upvotes: 0