Android CustomListView 更新的字段在向下滚动时重复

Android CustomListView updated fields are repeating when scrolled down

我在 customlist view 中遇到问题。

我有两个 buttons 和一个 textView 。添加和减去按钮。 单击 Add 按钮时,计数器应分别为 +1 和 -1。

我使用了一个虚拟字符串来检查它是否真的在更新 textView。但问题是当我 scroll down 一些项目具有相同的价值时。

例如 第一项 TextView 设置为 "HIII" 然后如果我向下滚动第 11 个,第 21 个 ... 也设置为 "HIII" 注意:显示可以包含的最大数量是 10 个项目,所以当我向下滚动到第 11 个时,它被设置为 "HII".

public class CustomAdapter extends ArrayAdapter {
    Context context;
    LayoutInflater inflater;
    int resource;
    //ArrayList<Integer> count = new ArrayList<>();




    public CustomAdapter(Context context, int resource) {
        super(context, resource);
        this.context = context;
        this.resource = resource;

    }

    @Override
    public int getCount() {
        return 100;
    }

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
       ViewHolder mainHolder = null;
        if (convertView == null) {
            inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = inflater.inflate(resource, parent, false);
            Log.e("GET-VIEW", " Creating Views");
           final ViewHolder holder = new ViewHolder();
            holder.add = (Button) convertView.findViewById(R.id.add);
            holder.sub = (Button) convertView.findViewById(R.id.sub);
            holder.textView = (TextView) convertView.findViewById(R.id.numberTV);
            holder.add.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    holder.textView.setText("HIII");
                }
            });
            convertView.setTag(holder);
        } else {
           mainHolder = (ViewHolder) convertView.getTag();
        }

        return convertView;
    }
}


class ViewHolder {

    Button add, sub;
    TextView textView;

}

请帮助我。我想知道如何设置一个与另一个的 tag(我的意思是你怎么知道你需要用另一个对象或视图设置标签)

谢谢

在 else 条件之后编写您的 onclick 侦听器。

holder.add.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                holder.textView.setText("HIII");
            }
        });

ListView 回收视图。它创建的视图将在向下滚动时重新使用。

因此,您必须在每次调用 getView() 时调用 setText()setOnClickListener(),而不仅仅是单击按钮时。

要实现您想要的效果,您必须将设置的文本数据存储在模型中,例如 SparseArray 将位置映射到数据。

public class CustomAdapter extends ArrayAdapter {
    Context context;
    LayoutInflater inflater;
    int resource;
    //ArrayList<Integer> count = new ArrayList<>();

    // Your data map by position
    SparseArray<String> data = new SparseArray<>();


    public CustomAdapter(Context context, int resource) {
        super(context, resource);
        this.context = context;
        this.resource = resource;

    }

    @Override
    public int getCount() {
        return 100;
    }

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
       final ViewHolder holder;
        if (convertView == null) {
            inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = inflater.inflate(resource, parent, false);
            Log.e("GET-VIEW", " Creating Views");
            holder = new ViewHolder();
            holder.add = (Button) convertView.findViewById(R.id.add);
            holder.sub = (Button) convertView.findViewById(R.id.sub);
            holder.textView = (TextView) convertView.findViewById(R.id.numberTV);
            convertView.setTag(holder);
        } else {
           holder = (ViewHolder) convertView.getTag();
        }

        holder.textView.setText(data.get(position));
        holder.add.setOnClickListener( new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                final String text = "HIII";
                data.put(position, text);
                holder.textView.setText(text);
                notifyDataSetChanged();
            }
        });

        return convertView;
    }
}

class ViewHolder {

    Button add, sub;
    TextView textView;

}

看看你的 getView 函数:

@Override
public View getView(final int position, View convertView, ViewGroup parent) {
   ViewHolder mainHolder = null;
    if (convertView == null) {
        inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView = inflater.inflate(resource, parent, false);
        Log.e("GET-VIEW", " Creating Views");
       final ViewHolder holder = new ViewHolder();
        holder.add = (Button) convertView.findViewById(R.id.add);
        holder.sub = (Button) convertView.findViewById(R.id.sub);
        holder.textView = (TextView) convertView.findViewById(R.id.numberTV);
        holder.add.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                holder.textView.setText("HIII");
            }
        });
        convertView.setTag(holder);
    } else {
       mainHolder = (ViewHolder) convertView.getTag();
    }

    return convertView;
}

只有在创建新的 Viewholder 时,您才能编辑持有人 textViewadd 按钮的内容。 列表视图第一次显示其项目时,总会为所有可见单元格创建一个新视图(以及一个新的 Viewholder)。 一旦您向下滚动,适配器将获取一个现在不可见的单元格(可能是第一个单元格)并回收它以显示一个现在可见的单元格。在这种情况下,getView 中的 convertView 将不再为 null,因为视图已被回收。 因此,您应该在 if 语句之外处理所有文本更改和监听器等,以管理这两种情况(回收的和新的)。 例如:

    if (convertView == null) {
        inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView = inflater.inflate(resource, parent, false);
        Log.e("GET-VIEW", " Creating Views");
        final ViewHolder holder = new ViewHolder();
        holder.add = (Button) convertView.findViewById(R.id.add);
        holder.sub = (Button) convertView.findViewById(R.id.sub);
        holder.textView = (TextView) convertView.findViewById(R.id.numberTV);

        convertView.setTag(holder);
    } else {
       mainHolder = (ViewHolder) convertView.getTag();
    }

    holder.textView.setText("");
    holder.add.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                holder.textView.setText("HIII");
            }
        });

编辑 将数据保存在像 Yaroslav Mytkalyk 这样的稀疏数组中是一种更好的方法。 无论如何,你必须处理回收的视图。