【问题标题】:GridView with custom ImageAdapter doesn't update after dataset changes具有自定义 ImageAdapter 的 GridView 在数据集更改后不会更新
【发布时间】:2012-08-06 17:17:28
【问题描述】:

我正在实现一个支持多项选择的图片库。主要布局是GridView,它使用自定义Adapter。每个显示的项目都是ImageView + CheckBox 的组合。如果选中了多个复选框,我想通过触摸GridView 中的任何图像来取消选中它们。我打电话给notifyDataSetChanged() 来实现这个功能。不幸的是,这个“取消选中所有”功能不起作用。我还是一个新手,所以可能有一些我不明白的基本内容。有人可以告诉我我的Adapter 有什么问题吗?谢谢。

public class ImageAdapter extends BaseAdapter {
    private Context mContext;

    // References to our images
    public Integer[] mThumbIds = {
            R.drawable.sample_1, R.drawable.sample_2, R.drawable.sample_3,
            R.drawable.sample_1, R.drawable.sample_2, R.drawable.sample_3,
            R.drawable.sample_1, R.drawable.sample_2, R.drawable.sample_3,
            R.drawable.sample_1, R.drawable.sample_2, R.drawable.sample_3
    };

    // The layout inflater used to retrieve gallery children layouts
    private LayoutInflater mInflater;

    // Array used to update checkboxes
    public boolean[] checkboxesState = new boolean[getCount()];

    public ImageAdapter(Context c) {
        mContext = c;
        mInflater = (LayoutInflater) 
                c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        // Define the initial checked/unchecked state of the checkboxes
        for(int i = 0; i < getCount(); i++) {
            checkboxesState[i] = false;
        }
    }

    public int getCount() {
        return mThumbIds.length;
    }

    public Object getItem(int position) {
        return position;
    }

    public long getItemId(int position) {
        return position;
    }

    /* Create a new View for each cell displayed in the GridView.
     * In our case a View is an instance of RelativeLayout from which
     * we can extract the image and checkbox to be displayed in the cell
     */
    public View getView(int position, View convertView, ViewGroup parent) {
        View cell = convertView;
        if (cell == null) {
            // No View passed, create one.
            cell = mInflater.inflate(R.layout.galleryitem, null);
            // Setup the View content
            ImageView imageView = (ImageView)cell.findViewById(R.id.thumbImage);
            CheckBox checkBox = (CheckBox) cell.findViewById(R.id.itemCheckBox);
            checkBox.setChecked(checkboxesState[position]);
            checkBox.setId(position);
            imageView.setImageBitmap(downsample(mThumbIds[position]));

            // Setup the View behavior
            imageView.setOnClickListener(new OnClickListener() {
                public void onClick(View v) {
                    // Uncheck all checked items
                    uncheckAll();
                }
            });

            checkBox.setOnClickListener(new OnClickListener() {
                public void onClick(View v) {
                    CheckBox cb = (CheckBox) v;
                    checkboxesState[cb.getId()] = cb.isChecked();
                }
            });
        }
        return cell;
    }

    private Bitmap downsample(int resId){
        // Some code here
    }

    private void uncheckAll() {
        // This code does not work. GridView is not refreshed
        for(int i = 0; i < checkboxesState.length; i++) {
            checkboxesState[i] = false;
        }
        notifyDataSetChanged();
    }
}

更新

我意识到我最初的帖子并没有准确描述 uncheckAll 方法是如何失败的。当我选中 N 个复选框并调用 uncheckAll 方法时会发生什么:

  • 最初选中的复选框未选中
  • 选中了一组新的 N 个复选框

这种行为让我想到可能是 gridview 项目出乎意料地改变了它们在GridView 中的位置,所以我为每个项目添加了一个具有唯一名称的TextView。我的想法是正确的:当我滚动屏幕时,这些项目会改变它们在GridView 中的位置。调用 uncheckAll 时也会发生同样的情况。我找到了适合我的解决方案in this thread。

注意:一开始我并没有意识到移动问题,因为在这个开发阶段我为每个 GridView 项目使用相同的 ImageView 资源。

【问题讨论】:

    标签: android gridview adapter


    【解决方案1】:

    问题很可能是您的 getView() 方法正确初始化了新的单元格视图,但从未更新已回收的单元格视图的状态。所以基本上每个单元格视图只会显示它被初始化的状态。它应该看起来像这样:

    public View getView(int position, View convertView, ViewGroup parent) {
        View cell = convertView;
    
        if (cell == null) {
            // No View passed, create one.
            cell = mInflater.inflate(R.layout.galleryitem, null);
            // Setup the View content
            ImageView imageView = (ImageView)cell.findViewById(R.id.thumbImage);
            CheckBox checkBox = (CheckBox) cell.findViewById(R.id.itemCheckBox);
            checkBox.setChecked(checkboxesState[position]);
            checkBox.setId(position);
            imageView.setImageBitmap(downsample(mThumbIds[position]));
    
            // Setup the View behavior
            imageView.setOnClickListener(new OnClickListener() {
                public void onClick(View v) {
                    // Uncheck all checked items
                    uncheckAll();
                }
            });
    
            checkBox.setOnClickListener(new OnClickListener() {
                public void onClick(View v) {
                    CheckBox cb = (CheckBox) v;
                    checkboxesState[cb.getId()] = cb.isChecked();
                }
            });
        } else {
            ImageView imageView = (ImageView)cell.findViewById(R.id.thumbImage);
            CheckBox checkBox = (CheckBox) cell.findViewById(R.id.itemCheckBox);
            checkBox.setChecked(checkboxesState[position]);
            checkBox.setId(position);
            imageView.setImageBitmap(downsample(mThumbIds[position]));
        }
    
        return cell;
    }
    

    另外,为了提高 getView() 方法的性能,请查看tutorial。

    【讨论】:

    • 感谢您的回答。它指向我在帖子更新中提到的线程的相同方向并且工作正常。我不知道教程。我会尝试将它应用到我的代码中。
    • 四年后我给你一票,对吧?那么我能说什么呢?这让我疯了!谢谢!
    猜你喜欢
    • 2013-03-29
    • 1970-01-01
    • 2014-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-19
    相关资源
    最近更新 更多