Представление перерабатывается даже при использовании держателя представления

Итак, я создал собственный список, один элемент которого использует этот макет:

<?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>

Пользовательский адаптер этого списка выглядит следующим образом:

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;
    }
}

Когда я нажимаю на элемент списка, его фон меняется на синий, но затем, когда я прокручиваю список вниз, я вижу, что другие элементы списка также получают синий фон. Я использую шаблон держателя представления, но почему он не работает? Почему до сих пор повторяется? Я что-то пропустил?

Заранее спасибо.

ОБНОВЛЕНИЕ: мне удалось немного исправить код, но проблема осталась. Хотя теперь представление не перерабатывается, когда я выбираю некоторые элементы списка сверху, но когда я прокручиваю вниз, а затем возвращаюсь вверх, я не вижу никакого дополнительного выбранного представления, а выбранные представления отменены. С другой стороны, когда я выбираю некоторые элементы списка в нижней части списка и прокручиваю вверх, я вижу, что они перерабатываются. Я не знаю, почему это происходит. Пожалуйста помоги.

Вот мой обновленный код:

@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);
}

person Mohammad Areeb Siddiqui    schedule 03.03.2015    source источник


Ответы (4)


Это не работает, потому что при повторном использовании иерархии View (и держателя представления) вы не сбрасываете цвет фона и текста в состояние по умолчанию. Обновите свой адаптер getView(), чтобы не только установить содержимое представлений, а также их цвета в состояние по умолчанию, и все должно быть хорошо.

person Larry Schiefer    schedule 03.03.2015

Используйте логический массив [] и установите его конкретную позицию true, которая получена методом getView в вашем методе щелчка.

Я думаю, это поможет вам

person Adnan Ali    schedule 03.03.2015

Повторно используйте представление, чтобы обновить фон представления и цвет текста в соответствии с вашим личным щелчком. Вы можете добиться этого, используя концепцию shareprefrence, как пример ниже .......

onClick вставить значение ключа в предпочтение общего доступа, где ключ должен быть позицией, а значение должно быть цветовым кодом

Вы можете использовать общие настройки для этой цели

onClick вставить значение ключа в общие настройки, где ключ должен быть позицией, а значение должно быть истинным/ложным

//В адаптере

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();
person Shadik Khan    schedule 03.03.2015

Сначала удалите свой final ViewHolder finalHolder = holder; и попробуйте это в своем 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));
            } 
        }
person Xcihnegn    schedule 06.03.2015
comment
Это просто сделает все невыбранным, когда я буду прокручивать вверх после выбора. - person Mohammad Areeb Siddiqui; 06.03.2015
comment
Хорошо, неправильно понял ваш вопрос! Я только что изменил свой ответ и надеюсь, что он сработает. - person Xcihnegn; 06.03.2015
comment
Можете ли вы предоставить мне правильный код в соответствии с обновленным кодом, который я предоставил? - person Mohammad Areeb Siddiqui; 06.03.2015
comment
Можете ли вы предоставить мне правильный код в соответствии с обновленным кодом, который я предоставил? - person Mohammad Areeb Siddiqui; 07.03.2015
comment
@MohammadAreebSiddiqui После того, как вы щелкнете элемент, contact будет правильным или нет? - person Xcihnegn; 07.03.2015
comment
Что вы подразумеваете под правильным? Если я правильно понял ваш вопрос, то иногда он показывает мне неправильное имя в журнале. - person Mohammad Areeb Siddiqui; 07.03.2015