halilkaya
halilkaya

Reputation: 467

ListView scrolling issue

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

Answers (4)

sajid45
sajid45

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

priyanka_rao
priyanka_rao

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

Kaushik
Kaushik

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

An SO User
An SO User

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

Related Questions