android - ListView - ViewHolder 设计的错误回收行为

标签 android listview android-arrayadapter

描述:


我目前正在使用 ViewHolder 设计模式实现自定义 ListViewAdapter。适配器正在使用带有按钮的布局,该按钮可切换 RelativeLayout 的可见性。

问题:


当我单击按钮并显示 RelativeLayout 时,一切似乎都正常,直到我向下滚动。 当我向下滚动时,我看到其他列表项已受到上一个按钮点击的影响,因此 RelativeLayout 在其他(错误的)项目上可见。 受到按钮点击影响的项目似乎是当我向下滚动时回收的那个。请注意,其他一切正常,文本等设置在正确的位置。

代码:


自定义列表适配器

public class ItemsListAdapter extends ArrayAdapter<Item> {
private Context mContext;
private List<Item> mItems;

public ItemsListAdapter(Context context, int resource, List<Item> objects) {
    super(context, resource);
    mContext = context;
    mItems = objects;
}

static class ViewHolder {
    View mView;
    boolean mExpanded;

    public ViewHolder(View view, boolean expanded)
    {
        mView = view;
        mExpanded = expanded;
    }
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View v = convertView;
    final Item item = getItem(position);

    final ViewHolder holder;
    if (v == null) {

        LayoutInflater mInflater = (LayoutInflater)
                mContext.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
        v = mInflater.inflate(R.layout.custom_list_item, null);

        holder = new ViewHolder(v, false);
        v.setTag(holder);
    } else {
        holder = (ViewHolder) v.getTag();
    }

    if(item != null)
    {
        TextView tvName = (TextView) holder.mView.findViewById(R.id.tv_name);
        tvName.setText(item.getName());

        RelativeLayout rlExpand = (RelativeLayout) holder.mView.findViewById(R.id.rl_expand);
        if(holder.mExpanded) {
            rlExpand.setVisibility(View.VISIBLE);
        }
        else {
            rlExpand.setVisibility(View.GONE);
        }

        TextView tvDescription = (TextView) holder.mView.findViewById(R.id.tv_description);
        if(tvDescription != null)
            tvDescription.setText(item.getDescription());

        final ImageButton ibExpand = (ImageButton) holder.mView.findViewById(R.id.ib_expand);
        ibExpand.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                RelativeLayout rlExpand = (RelativeLayout) holder.mView.findViewById(R.id.rl_expand);
                if (rlExpand.getVisibility() == View.GONE) {
                    v.setVisibility(View.INVISIBLE);
                    rlExpand.setVisibility(View.VISIBLE);
                    holder.mExpanded = true;
                }
            }
        });

        ImageButton ibCollapse = (ImageButton) holder.mView.findViewById(R.id.ib_collapse);
        ibCollapse.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                RelativeLayout rlExpand = (RelativeLayout) holder.mView.findViewById(R.id.rl_expand);
                ibExpand.setVisibility(View.VISIBLE);
                rlExpand.setVisibility(View.GONE);
                holder.mExpanded = false;
            }
        });


    }

    return v;
}

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

@Override
public Truism getItem(int position) {
    return mItems.get(position);
}

非常感谢任何帮助!提前致谢!

最佳答案

尝试改变:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View v = convertView;
    final Item item = getItem(position);

    final ViewHolder holder;
    if (v == null) {

        LayoutInflater mInflater = (LayoutInflater)
                mContext.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
        v = mInflater.inflate(R.layout.custom_list_item, null);

        holder = new ViewHolder(v, false);
        v.setTag(holder);
    } else {
        holder = (ViewHolder) v.getTag();
    }

    if(item != null)
    {
        TextView tvName = (TextView) holder.mView.findViewById(R.id.tv_name);
        tvName.setText(item.getName());

        RelativeLayout rlExpand = (RelativeLayout) holder.mView.findViewById(R.id.rl_expand);
        if(item.isExpanded) {
            rlExpand.setVisibility(View.VISIBLE);
        }
        else {
            rlExpand.setVisibility(View.GONE);
        }

        TextView tvDescription = (TextView) holder.mView.findViewById(R.id.tv_description);
        if(tvDescription != null)
            tvDescription.setText(item.getDescription());

        [...]
    }

    return v;
}

holder.mExpanded 更改为 item.isExpanded

关于android - ListView - ViewHolder 设计的错误回收行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34962577/

相关文章:

android - 从服务中获取对 ProgressDialog 的引用

c# - ASP.NET ListView 控件未触发 OnItemCommand 事件

css - 带有 JavaFX 的 ListView 中的颜色特定行

android - Textview 不在自定义 ListView 中滚动

Android - GridView 的行为非常奇怪

Android 以编程方式配对后自动连接蓝牙设备

android - CREATOR 对象在类 com.example.android.movi​​eapp.Movie 上是静态的

java - Android 地理围栏不触发 IntentService

android - 如何使用 Tag 代替 R.id。在自定义 ArrayAdapter 的构造函数中?

android - 调用 ArrayAdapter 导致无限循环?