当我尝试使用延迟加载的imageViews作为组视图创建可扩展的列表视图时,我遇到了一个不好的问题。结果表明,每次打开一个组时,所有的组视图都会重新绘制,但会给它们一个随机的convertView(而不是他们的),这会导致非常糟糕的闪烁,因为之前的imageViews被randomely传递给了错误的组。您可以通过以下示例来体验此问题,该示例包含一个非常简单的ExpandableListView,具有延迟的组绘制,可以很好地突出显示这种不需要的行为。是否有更好的实现保留了在组开口上绑定的item / convertView?
-respondsToSelector:
答案 0 :(得分:0)
你需要两个视图持有者一个用于父级,另一个用于子元素。
你可以尝试这样的事情。 public class MyExpandableListAdapter扩展了BaseExpandableListAdapter {private Context mContext;
private ArrayList<ContactNameItems> mListDataHeader;
private ArrayList<String> selectedNumbers;
private HashMap<String, List<ContactPhoneItems>> mListDataChild;
private ChildViewHolder childViewHolder;
private GroupViewHolder groupViewHolder;
public MyExpandableListAdapter(Context context,
ArrayList<ContactNameItems> listDataHeader,
HashMap<String, List<ContactPhoneItems>> listDataChild,
ArrayList<String> listOfNumbers) {
mContext = context;
mListDataHeader = listDataHeader;
mListDataChild = listDataChild;
selectedNumbers = listOfNumbers;
}
@Override
public int getGroupCount() {
return mListDataHeader.size();
}
@Override
public ContactNameItems getGroup(int groupPosition) {
return mListDataHeader.get(groupPosition);
}
@Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
@Override
public View getGroupView(int groupPosition, boolean isExpanded,
View convertView, ViewGroup parent) {
String contactName = getGroup(groupPosition).getName();
Bitmap contactImage = getGroup(groupPosition).getImage();
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.contact_name_item, null);
groupViewHolder = new GroupViewHolder();
groupViewHolder.mContactName = (TextView) convertView
.findViewById(R.id.lblListHeader);
groupViewHolder.mContactImage = (ImageView) convertView
.findViewById(R.id.ivContactPhoto);
convertView.setTag(groupViewHolder);
} else {
groupViewHolder = (GroupViewHolder) convertView.getTag();
}
if (contactImage != null) {
groupViewHolder.mContactImage.setImageBitmap(contactImage);
} else {
groupViewHolder.mContactImage
.setImageResource(R.drawable.default_contact);
}
groupViewHolder.mContactName.setText(contactName);
return convertView;
}
@Override
public int getChildrenCount(int groupPosition) {
return mListDataChild.get(mListDataHeader.get(groupPosition).getName())
.size();
}
@Override
public ContactPhoneItems getChild(int groupPosition, int childPosition) {
return mListDataChild.get(mListDataHeader.get(groupPosition).getName())
.get(childPosition);
}
@Override
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
@Override
public View getChildView(int groupPosition, final int childPosition,
boolean isLastChild, View convertView, ViewGroup parent) {
String numberText = getChild(groupPosition, childPosition).getNumber();
String typeText = getChild(groupPosition, childPosition).getPhoneType();
final int mGroupPosition = groupPosition;
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) this.mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.contact_detail_item, null);
childViewHolder = new ChildViewHolder();
childViewHolder.mPhoneNumber = (TextView) convertView
.findViewById(R.id.tv_phone_number);
childViewHolder.mPhoneType = (TextView) convertView
.findViewById(R.id.tv_phone_type);
childViewHolder.mCheckBox = (CheckBox) convertView
.findViewById(R.id.checkBox);
childViewHolder.mCheckBox.setOnCheckedChangeListener(checkListener);
convertView.setTag(childViewHolder);
} else {
childViewHolder = (ChildViewHolder) convertView.getTag();
}
childViewHolder.mPhoneNumber.setText(numberText);
childViewHolder.mPhoneType.setText(typeText);
ContactPhoneItems cpi = getChild(mGroupPosition, childPosition);
childViewHolder.mCheckBox.setTag(cpi);
childViewHolder.mCheckBox.setChecked(cpi.getSelected());
// for managing the state of the boolean
// array according to the state of the
// CheckBox
childViewHolder.mCheckBox
.setOnClickListener(new View.OnClickListener() {
String contactNumber = mListDataChild
.get(mListDataHeader.get(mGroupPosition).getName())
.get(childPosition).getNumber();
public void onClick(View v) {
boolean isChecked = ((CheckBox) v).isChecked();
if (isChecked) {
selectedNumbers.add(contactNumber);
} else {
selectedNumbers.remove(contactNumber);
}
getChild(mGroupPosition, childPosition).setSelected(isChecked);
notifyDataSetChanged();
}
});
return convertView;
}
@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return false;
}
@Override
public boolean hasStableIds() {
return false;
}
public ArrayList<String> getSelectedNumbers() {
return selectedNumbers;
}
public final class GroupViewHolder {
TextView mContactName;
ImageView mContactImage;
}
public final class ChildViewHolder {
TextView mPhoneNumber;
TextView mPhoneType;
CheckBox mCheckBox;
}
OnCheckedChangeListener checkListener = new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
ContactPhoneItems c = (ContactPhoneItems) buttonView.getTag();
c.setSelected(isChecked);
}
};
}