Android 带有 CustomAdapter 显示工件的 ExpandableListView

Android ExpandableListView with CustomAdapter display artifacts

我遇到了 ExpandableListView 和自定义适配器的错误 看起来 TextView 没有自己的价值,你可以在视频中看到。模型仅在此列表中不更改此值

Name 和phone 不影响,但是两个右边的textview 是。

https://www.youtube.com/embed/YjC_QsA75yo

有人遇到过这个错误吗? 知道如何追踪和修复它吗?

更新

public ExpandableAdapter(List<CategoryModel> categoryModels, Context ctx) {
    this.categoryModels = categoryModels;
    this.ctx = ctx;
}

@Override
public int getGroupCount() {
    return categoryModels.size();
}

@Override
public int getChildrenCount(int groupPosition) {
    return categoryModels.get(groupPosition).getMembers().size();
}

@Override
public Object getGroup(int groupPosition) {
    return categoryModels.get(groupPosition);
}

@Override
public Object getChild(int groupPosition, int childPosition) {
    return categoryModels.get(groupPosition).getMembers().get(childPosition);
}

@Override
public long getGroupId(int groupPosition) {
    return categoryModels.get(groupPosition).getId();
}

@Override
public long getChildId(int groupPosition, int childPosition) {
    return categoryModels.get(groupPosition).getMembers().get(childPosition).getId();
}

@Override
public boolean hasStableIds() {
    return true;
}

@Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {

    View v = convertView;
    if (v == null) {
        LayoutInflater inflater = (LayoutInflater) ctx.getSystemService
                (Context.LAYOUT_INFLATER_SERVICE);
        v = inflater.inflate(R.layout.reg_group_layout, parent, false);
    }

    TextView groupName = (TextView) v.findViewById(R.id.tv_group_name);
    TextView groupCount = (TextView) v.findViewById(R.id.tv_group_count);

    CategoryModel cat = categoryModels.get(groupPosition);
    groupName.setText(cat.toString());
    groupCount.setText(cat.getMembers().size() + "");

    return v;
}

@Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {

    View v = convertView;

    if (v == null) {
        LayoutInflater inflater = (LayoutInflater) ctx.getSystemService
                (Context.LAYOUT_INFLATER_SERVICE);
        v = inflater.inflate(R.layout.reg_member_layout, parent, false);
    }

    TextView tvName = (TextView) v.findViewById(R.id.tv_reg_mem_name);
    TextView tvPhone = (TextView) v.findViewById(R.id.tv_reg_mem_phone);
    TextView tvFinishTime = (TextView) v.findViewById(R.id.tv_reg_finishtime);
    TextView tvPenaltyTime = (TextView) v.findViewById(R.id.tv_reg_penaltytime);

    MemberModel mem = (MemberModel) getChild(groupPosition, childPosition);

    if (!mem.getActive()) {
        tvName.setTextColor(Color.GRAY);
        tvPhone.setTextColor(Color.GRAY);
    } else {
        tvName.setTextColor(Color.BLACK);
        tvPhone.setTextColor(Color.BLACK);
    }

    tvName.setText(mem.getMem_name());
    tvPhone.setText(mem.getMem_tel());
    Util.setFinishTime(tvFinishTime, mem.getFinishTime());
    Long penTime = mem.getPenaltyTime();
    if (penTime != null && penTime != 0) {
        Util.setPenaltyTime(tvPenaltyTime, penTime);
    } else {
        //tvPenaltyTime.setVisibility(View.INVISIBLE);
    }
    return v;
}


@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
    return true;
}

@Override
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
    return true;
}

@Override
public void registerDataSetObserver(DataSetObserver observer) {
    super.registerDataSetObserver(observer);
}

确保始终设置 FinishTime 和 Penaltytime,如果为空,甚至设置为空格。

发生了什么事,您得到了 convertViews(旧内容的旧视图),您需要用新内容填充它们。这些行:

  if (penTime != null && penTime != 0) {
        Util.setPenaltyTime(tvPenaltyTime, penTime);
    } else {
        //tvPenaltyTime.setVisibility(View.INVISIBLE);
    }

如果不为 0 将设置惩罚时间,但如果为 0,则将保留旧视图的旧值,无论它是什么。这就是为什么当有惩罚时间的行退出屏幕时,进入屏幕的新视图将保留旧的惩罚时间(如果没有)。

学习 View Recycling 的工作原理是值得的!您可以通过使用 ViewHolder 和缓存 findViewById's.

进一步优化您的适配器

所以你可以这样做:

    if (penTime != null && penTime != 0) {
        Util.setPenaltyTime(tvPenaltyTime, penTime);
    } else {
        Util.setPenaltyTime(tvPenaltyTime, 0);
    }

或者,正如您尝试的那样,

    if (penTime != null && penTime != 0) {
        Util.setPenaltyTime(tvPenaltyTime, penTime);
        tvPenaltyTime.setVisibility(View.VISIBLE);
    } else {
        tvPenaltyTime.setVisibility(View.INVISIBLE);
    }