在 Android 的 ListView 上选择项目的奇怪操作

Strange actions with item selection on a ListView in Android

在这让我彻底疯掉之前,有人可以帮忙吗!

假设您有一个列表视图。它有 9 个项目,但只有 space 可以在不滚动的情况下显示 6 个。如果某个项目被 select 编辑,背景颜色将更改以表明这一点。

如果你select 任何从 2 到 8 的项目都很好。

如果您 select 项目 1,它也会 select 项目 9,反之亦然。同样对于这个selection,如果你上下滚动随机次数,selection 将会改变。如果您继续上下滚动,selection 会变回 1 和 9。selected 项目的值始终是您 selected 的实际项目。

这是我的适配器代码:

public class AvailableJobAdapter extends ArrayAdapter<JobDto> {

    private Context context;
    private ArrayList<JobDto> items;
    private LayoutInflater vi;

    public AvailableJobAdapter(Context context, ArrayList<JobDto> items) {
        super(context, 0, items);
        this.context = context;
        this.items = items;
        vi = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        ViewHolder holder = null;

        JobDto jh = getItem(position);

        if (convertView == null) {
            convertView = vi.inflate(R.layout.inflator_job_list, null);

            holder = new ViewHolder();

            holder.numberText = (TextView) convertView.findViewById(R.id.txtNumber);
            holder.descriptionText = (TextView) convertView.findViewById(R.id.txtDescription);
            holder.statusText = (TextView) convertView.findViewById(R.id.txtStatus);

            convertView.setTag(holder);

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

        holder.numberText.setText(jh.getJobNumber());
        holder.descriptionText.setText(jh.getDescription());
        holder.statusText.setText(jh.getStatus());

        return convertView;
    }

    public static class ViewHolder {
        public TextView numberText;
        public TextView descriptionText;
        public TextView statusText;
    }
}

这是来自我的点击监听器的代码:

jobs.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                Button btnOk = (Button) findViewById(R.id.btnOk);

                view.setSelected(true);

                int selected = position;

                int pos = val.get(selected);

                int firstItem = jobs.getFirstVisiblePosition();
                int viewIndex = selected - firstItem;

                if (pos == 0) {


                    jobs.getChildAt(viewIndex).setBackgroundColor(getResources().getColor(R.color.selected));

                    val.set(selected, 1);

                    selectedCount ++;

                } else {

                    jobs.getChildAt(viewIndex).setBackgroundColor(getResources().getColor(R.color.unselected));

                    val.set(selected, 0);

                    selectedCount --;
                }

                if (selectedCount > 0 ){
                    btnOk.setEnabled(true);
                } else {
                    btnOk.setEnabled(false);
                }

            }

        });

我花了几个小时研究这个问题并尝试了各种建议。

任何帮助将不胜感激。

****编辑**** 在考虑了一些建议后,我用一个巨大的列表对其进行了测试。这正是行为的本质:-

如果您的屏幕有 10 个项目 space,如果您 select 项目 1,它还会突出显示 11、21、31、41 等

这些值之间的任何值都可以正常运行。

在 setOnItemClickListener() 中,只需将点击位置的 setSelected() true 或 false 更新并通知数据集。在 getView 中放一个条件

if(jh.isSelelcted())
{
// background is selected color
}else{
// background is non selected color
}

注意:处理 else 条件。

来自this guide

When your ListView is connected to an adapter, the adapter will instantiate rows until the ListView has been fully populated with enough items to fill the full height of the list. At that point, no additional row items are created in memory.

Instead, as the user scroll through the list, items that leave the screen are kept in memory for later use and then every new row that enters the screen reuses an older row kept around in memory. In this way, even for a list of 1000 items, only ~7 item view rows are ever instantiated or held in memory.

这就是您面临的问题的根源。您正在更改点击监听器中视图的背景颜色。但是一旦选定的项目滚出屏幕,它的视图将被重新用于滑入的新项目。由于重新使用的视图改变了背景颜色,因此新项目将具有相同的颜色。

您需要考虑到视图是可回收的,因此当您在 getView() 中获取它们时它们可能是“脏的”。我建议你看一下我从上面引述的地方得到的指南,这是一本很好的重要读物。

解决这个问题的一种可能方法是向您的 JobDto class 添加一个布尔字段,并使用它来跟踪是否选择了某个项目。然后在 getView() 中,您可以相应地更新背景颜色。您可能还需要将项目根视图 (convertView) 添加到您的 ViewHolder 以更改其背景颜色。