1

我有一个GridView其元素基于一个FrameLayout包含一个ImageView和一个CheckedTextView。FrameLayout的xml文件如下:

<FrameLayout
xmlns:android = "http://schemas.android.com/apk/res/android"
android:id="@+id/gridImage"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:gravity="center_horizontal">
<ImageView
android:id="@+id/image"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:adjustViewBounds="false">
</ImageView>
<CheckedTextView
android:id="@+id/imageTick"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:layout_gravity="center_horizontal|bottom"
android:checkMark="@drawable/icon"
android:checked="false"
android:visibility="invisible"
>
</CheckedTextView>
</FrameLayout>

编辑:这是getView()我用于每个元素的适配器方法:

public View getView(int position, View convertView, ViewGroup parent) {
        Log.d("getView()", position+"");
        View v;
        ImageView imageView;
        if(convertView == null) {

            v = LayoutInflater.from(mContext).inflate(R.layout.photo_text_view, null);
            v.setLayoutParams(new GridView.LayoutParams(100,100));
        }
        else
        {
            v = convertView;

        }
        imageView = (ImageView) v.findViewById(R.id.image);
        imageView.setImageBitmap(mThumbsIds.get().get(position));

        v.setPadding(8, 8, 8, 8);
        return v;
    }

在我的活动类中,我加载了一个上下文菜单,一旦我选择了一个选项,我就会使该元素CheckedTextView可见,如下所示:GridView

GridView gridView = (GridView) findViewById(R.id.gridview);
    View selected =gridView.getChildAt(position);
    CheckedTextView selectedCheck = (CheckedTextView)selected.findViewById(R.id.imageTick);
    selectedCheck.setChecked(true);
    selectedCheck.setVisibility(View.VISIBLE);

因此,从这一点开始可能会发生两件事:

1) 假设我在位置 0 选择了元素,CheckedTextView 变得可见,但是当我向下滚动 GridView 时,另一个元素(例如位置 17)的 CheckedTextView 也可见。当我向下滚动到底部时,这会在随机元素上继续。

2)如果我选择一个朝向底部的元素,向上滚动到顶部,然后运行一种方法使所有 CheckedTextView 不可见,NullPointerException则会为底部的元素抛出一个。这发生在这一点上:View selected =gridView.getChildAt(position);其中 selected 变为 null。

这里发生了什么?为什么这些随机 CheckedTextView 变得可见,为什么会出现异常?

4

1 回答 1

1

问题在于您跟踪检查项目的方式:

GridView gridView = (GridView) findViewById(R.id.gridview);
View selected =gridView.getChildAt(position);
CheckedTextView selectedCheck = (CheckedTextView)selected.findViewById(R.id.imageTick);
selectedCheck.setChecked(true);
selectedCheck.setVisibility(View.VISIBLE);

1)getChildAt如果您滚动到内容并且您正在按适配器位置进行索引,则不会为您提供正确的视图。当引用 a 中的活动视图时,GridView或者ListView您想要执行以下操作:

final int index = position - gridView.getFirstVisiblePosition();
View selected = gridView.getChildAt(index);

原因是您GridView只保留当前显示的适配器项目的子视图。如果元素 0 到 3 早先从顶部滚动,它可能只有元素 4 到 23 的子视图。

这就是为什么当您View selected =gridView.getChildAt(position);对该位置进行视图时遇到异常的原因,当它在屏幕外时实际上并不存在,所以getChildAt返回null

2) 当 a ListVieworGridView的内容发生变化或者它需要重新布局其子视图时,它通过使用convertView参数将现有视图重新绑定到您的适配器来实现。您的适配器永远不会调整项目视图的选中状态,因此可以将选中的视图重用于以后应该取消选中的项目。

为了解决这个问题,您应该让您的适配器呈现的数据模型跟踪您的项目的检查状态,而不是依赖项目视图来执行它。这意味着您的适配器应始终验证/设置项目的选中状态getView。它可能看起来像这样:

imageView = (ImageView) v.findViewById(R.id.image);
imageView.setImageBitmap(mThumbsIds.get().get(position));

CheckedTextView checkView = (CheckedTextView) v.findViewById(R.id.imageTick);

if (mData.isItemChecked(position)) {
    checkView.setChecked(true);
    checkView.setVisibility(View.VISIBLE);
} else {
    checkView.setVisibility(View.GONE);
}

然后,当您选择应该更改项目的选中状态的选项时,而不是上面的代码片段,请执行以下操作:

data.setItemChecked(position, true);
adapter.notifyDataSetChanged();

notifyDataSetChanged()将告诉GridView它应该重新绑定项目视图,这将使您的getView方法正确修复检查的状态。

于 2011-05-01T20:29:55.587 回答