即使使用视图持有者,视图也在回收

时间:2015-03-03 18:32:41

标签: android listview android-viewholder

所以我创建了一个自定义列表视图,其中一个项目使用此布局:

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

当我点击listitem时,它的背景变为蓝色,但是当我向下滚动列表视图时,我看到其他列表项也变为蓝色背景。我正在使用视图持有人模式,但为什么它不起作用?为什么还在重复?我错过了什么吗?

提前致谢。

更新:我能够纠正我的代码,但问题仍然存在。虽然现在当我从顶部选择一些列表项时视图不回收但是当我向下滚动然后再回来时我没有看到任何额外的视图被选中而是取消选择了所选的视图。另一方面,当我从列表视图的底部选择一些列表项并向上滚动时,我看到它们正在回收。我不知道为什么会这样。请帮忙。

这是我更新的代码:

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

4 个答案:

答案 0 :(得分:0)

它不起作用,因为当您重新使用View层次结构(和视图持有者)时,您没有将背景和文本颜色重置为默认状态。更新您的适配器getView(),不仅要将视图的内容设置为默认状态,还应该是好的。

答案 1 :(得分:0)

使用boolean []数组并将其特定位置设置为true,这是通过点击方法的getView方法获得的

我认为它会对你有所帮助

答案 2 :(得分:0)

重复使用视图需要根据您的私密点击更新视图背景和文本颜色。你可以通过使用shareprefrence概念来实现这一点,如下面的示例.......

onClick在共享首选项中插入键值,其中键应该是位置,值应该是颜色代码

您可以为此目的使用共享偏好

onClick在sharedpreferences中插入键值,其中键应该是位置,值应该是true / false

//在适配器

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();

答案 3 :(得分:0)

首先删除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));
            } 
        }