0

So I have created a custom listview of which one item uses this layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:padding="5dp"
    android:minHeight="?android:attr/listPreferredItemHeight"
    android:gravity="center_vertical"
    android:paddingLeft="5dp"
    android:id="@+id/llContactRow"
    android:orientation="horizontal">

    <CheckBox
        android:id="@+id/cbMultipleSelect"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:drawableRight="@android:color/transparent"
        android:clickable="false"
        android:layout_weight="0"
        />

    <com.pkmmte.view.CircularImageView
        android:id="@+id/ivContactPicture"
        android:layout_width="0dp"
        android:layout_height="50dp"
        android:layout_weight="0.2"
        android:src="@drawable/user_default"
        android:paddingLeft="10dp"
        app:civ_shadow="true" />

    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:gravity="center_vertical"
        android:orientation="vertical"
        android:paddingLeft="20dp"
        android:id="@+id/llContactDetails"
        android:layout_weight="1">

        <TextView
            android:id="@+id/tvContactName"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Areeb"
            android:textAppearance="?android:attr/textAppearanceMedium" />

        <TextView
            android:id="@+id/tvContactNumber"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="03342228458" />

    </LinearLayout>

    <ImageView
        android:layout_width="0dp"
        android:layout_height="16dp"
        android:id="@+id/ivContactSelectionTick"
        android:src="@drawable/contact_selection_tick"
        android:visibility="invisible"
        android:layout_weight="0.2" />

</LinearLayout>

The custom adapter of this listview is as follows:

import java.util.ArrayList;
import java.util.List;

import com.footstapps.contactshelper.ContactInfo;
import com.footstapps.letsmeet.R;
import com.pkmmte.view.CircularImageView;

import android.content.Context;
import android.graphics.Color;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

public class ContactsListAdapter extends BaseAdapter{

    private Context context;
    private List<ContactInfo> contacts;
    private List<ContactInfo> selectedContacts;

    public ContactsListAdapter(Context context, List<ContactInfo> contacts) {
        this.context = context;
        this.contacts = contacts;
        selectedContacts = new ArrayList<ContactInfo>();
    }

    public List<ContactInfo> getSelectedContacts() {
        return selectedContacts;
    }

    @Override
    public int getCount() {
        return contacts.size();
    }

    @Override
    public Object getItem(int position) {
        return contacts.get(position);
    }

    @Override
    public long getItemId(int position) {
        return Long.parseLong(contacts.get(position).id);
    }

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        ViewHolder holder = new ViewHolder();


        if(convertView == null) {
            convertView = inflater.inflate(R.layout.contacts_list_row_item, null);
            holder.view = (LinearLayout) convertView.findViewById(R.id.llContactRow);
            holder.contactPicture = (CircularImageView) convertView.findViewById(R.id.ivContactPicture);
            holder.name = (TextView) convertView.findViewById(R.id.tvContactName);
            holder.number = (TextView) convertView.findViewById(R.id.tvContactNumber);
            holder.checkbox = (CheckBox) convertView.findViewById(R.id.cbMultipleSelect);
            holder.selectedTick = (ImageView) convertView.findViewById(R.id.ivContactSelectionTick);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        final ViewHolder finalHolder = holder;

        holder.name.setText(contacts.get(position).name);
        holder.number.setText(contacts.get(position).number);
        holder.checkbox.setChecked(selectedContacts.contains(contacts.get(position)));

        holder.view.setOnClickListener(new OnClickListener() { 

            @Override 
            public void onClick(View v) {
                finalHolder.checkbox.setChecked(!finalHolder.checkbox.isChecked());
                if(finalHolder.checkbox.isChecked()) {
                    finalHolder.view.setBackgroundColor(Color.parseColor("#33b5e5"));
                    finalHolder.name.setTextColor(Color.WHITE);
                    finalHolder.number.setTextColor(Color.WHITE);
                    //finalHolder.selectedTick.setVisibility(View.VISIBLE);
                    selectedContacts.add(contacts.get(position)); 
                } else {
                    finalHolder.view.setBackgroundColor(Color.TRANSPARENT);
                    finalHolder.name.setTextColor(Color.BLACK);
                    finalHolder.number.setTextColor(Color.BLACK);
                    //finalHolder.selectedTick.setVisibility(View.INVISIBLE);
                    selectedContacts.remove(contacts.get(position));
                } 
            } 
        });

        return convertView;
    }

    private static class ViewHolder {
        LinearLayout view;
        CircularImageView contactPicture;
        CheckBox checkbox;
        TextView name;
        TextView number;
        ImageView selectedTick;
    }
}

When I click on a listitem it's background changes to blue but then when I scroll down the list view I see other list items also getting a blue background. I am using a view holder pattern but why it isn't working? Why is it still repeating? Did I miss something?

Thanks in advance.

UPDATE: I was able to correct my code a bit but still the problem remains. Although now the view is not recycling when I select some list items from the top but when I scroll down then come back up I do not see any extra view selected rather the selected views deselected. On the other hand when I select some list items from the bottom part of the listview and scroll up I see them recycling. I do not know why is that happening. Please help.

Here is my updated code:

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

    final ContactInfo contact = contacts.get(position);
    final ViewHolder holder;

    if(convertView == null) {
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        holder = new ViewHolder();

        convertView = inflater.inflate(R.layout.contacts_list_row_item, null);
        holder.view = (LinearLayout) convertView.findViewById(R.id.llContactRow);
        holder.contactPicture = (CircularImageView) convertView.findViewById(R.id.ivContactPicture);
        holder.name = (TextView) convertView.findViewById(R.id.tvContactName);
        holder.number = (TextView) convertView.findViewById(R.id.tvContactNumber);
        holder.selectedTick = (ImageView) convertView.findViewById(R.id.ivContactSelectionTick);
        convertView.setTag(holder);

        holder.view.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                if(!selectedContacts.contains(contact)) {
                    setListItemSelected(holder);
                    selectedContacts.add(contact);
                } else {
                    setListItemUnselected(holder);
                    selectedContacts.remove(contact);
                }

                for(ContactInfo con : selectedContacts){
                    Log.d("Adapter", con.name);
                }
            }
        });

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

    if(!selectedContacts.contains(contact)) {
        setListItemUnselected(holder);
    }

    holder.name.setText(contact.name);
    holder.number.setText(contact.number);

    return convertView;
}

private void setListItemSelected(ViewHolder holder) {
    holder.view.setBackgroundColor(Color.parseColor("#33b5e5"));
    holder.name.setTextColor(Color.WHITE);
    holder.number.setTextColor(Color.WHITE);
    holder.selectedTick.setVisibility(View.VISIBLE);
}

private void setListItemUnselected(ViewHolder holder) {
    holder.view.setBackgroundColor(Color.TRANSPARENT);
    holder.name.setTextColor(Color.BLACK);
    holder.number.setTextColor(Color.BLACK);
    holder.selectedTick.setVisibility(View.INVISIBLE);
}
Mohammad Areeb Siddiqui
  • 9,795
  • 14
  • 71
  • 113

4 Answers4

0

It's not working because when you re-use the View hierarchy (and view holder), you are not resetting the background and text color to a default state. Update your adapter getView() to not only set the content of the views by also their colors to a default state and you should be good.

Larry Schiefer
  • 15,687
  • 2
  • 27
  • 33
0

Use a boolean[] array and set its specific position true which is got by getView method at your on click method

I think it will help you

Adnan Ali
  • 792
  • 1
  • 8
  • 21
0

Reuse the view needs to update the view background and textcolor as per your privious click. You can acheive this by using shareprefrence concept like sample below.......

onClick insert key value in share preference where key should be position and value should be color code

You can use shared preference for this purpose

onClick insert key value in sharedpreferences where key should be position and value should be true/false

//In Adapter

if(sharedpreferences.contains(String.valueof(position)) && sharedpreferences.getString(String.valueof(position), "").equals("colorcode")){

//update view background to colorcode and textview color

}

else{
 // default
}

//onClick
Editor editor = sharedpreferences.edit();
editor.putString(String.valueof(position)), "colorcode");
editor.commit();
Shadik Khan
  • 1,217
  • 1
  • 8
  • 18
0

Firstly remove your final ViewHolder finalHolder = holder; , and try this in your getView(...):

holder.view.setOnClickListener(new OnClickListener() { 

        @Override 
        public void onClick(View v) {
            ViewHolder holder = (ViewHolder)v.getTag();

            holder.checkbox.setChecked(!holder.checkbox.isChecked());
            if(holder.checkbox.isChecked()) {
                holder.view.setBackgroundColor(Color.parseColor("#33b5e5"));
                holder.name.setTextColor(Color.WHITE);
                holder.number.setTextColor(Color.WHITE);
                //holder.selectedTick.setVisibility(View.VISIBLE);
                selectedContacts.add(contacts.get(position)); 
            } else {
                holder.view.setBackgroundColor(Color.TRANSPARENT);
                holder.name.setTextColor(Color.BLACK);
                holder.number.setTextColor(Color.BLACK);
                //holder.selectedTick.setVisibility(View.INVISIBLE);
                selectedContacts.remove(contacts.get(position));
            } 
        }
Xcihnegn
  • 11,579
  • 10
  • 33
  • 33