CursorAdapter在滚动期间自定义视图无法正确更新

时间:2014-05-08 16:46:56

标签: android android-custom-view android-adapter

我有一个自定义视图,它基本上是一个圆圈,使用填充颜料或描边颜料绘制,具体取决于数据库中的列,从而形成一个实心圆圈或圆环。

我的活动包含使用游标适配器从数据库填充的这些圈子的网格。在适配器的bindView中,我在自定义视图上设置属性,例如制作圆圈的颜色以及是否绘制为“填充”圆圈或圆环的布尔标记。

public void bindView(View view, Context context, Cursor cursor) {
    CustomCircle circle = (CustomCircle) view.findViewById(R.id.custom_circle);

    // Set up the color of the Circle
    int index = cursor.getColumnIndex("Color");
    String colorString = "#" + cursor.getString(index);
    int color = Color.parseColor(colorString);
    circle.setFillColor(color);        

    // Set up the layout of the circle
    index = cursor.getColumnIndex("count");
    int totalCount = cursor.getInt(index);
    if (totalCount > 0)
    {
        circle.setFillInCircle(true);
    }
}

在自定义视图的onSizeChanged内部,我必须修改直径以调整笔触大小,因为笔划宽度在朝向和远离圆心的同等距离内增长。

在最初的OnCreateView调用中,我通过调用设置游标适配器,以按颜色顺序获取所有元素。这最初看起来很好,因为所有元素都被标记为默认绘制为环。但是,一旦我修改网格视图的顶行或底行中的一个圆元素(由于屏幕的大小,另一个在视图中时,其中一行将不在视图中),问题就会开始发生被'填补'。

现在,不规律地,我看到的行为是,两端的某些元素将被绘制为实心圆,但是具有用于笔触样式的小直径。这包括打开填充的自定义视图和未打开的自定义视图。您可以向上和向下滚动,它们的圆圈将有不同的配置!

onDraw调用中的断点显示报告的半径为较小的样式但填充标记打开的情况(应该关闭时)。

所以我想弄清楚滚动过程中发生了什么。我假设光标适配器将懒惰地重新绑定元素,从而更新所有必需的属性,然后将调用onSizeChanged,从而确保我的逻辑是合理的。不幸的是,看起来onSizeChanged有时只会触发。

在视图绑定方面,onSizeChanged和onDraw在使用游标适配器映射到数据的网格滚动期间会发生什么?

1 个答案:

答案 0 :(得分:1)

我找到了解决方案 - 这是两个问题。

首先,滚动时无法保证onSizeChanged执行。我将逻辑移到onMeasure并确保我正在调用requestLayout()以获得正确的直径。

其次,适配器重用视觉效果。这意味着您必须更新每个属性以确保它们是正确的;您无法保证类默认值为true。在我的情况下,我更新了上面的方法,如下所示:

public void bindView(View view, Context context, Cursor cursor) {
    CustomCircle circle = (CustomCircle) view.findViewById(R.id.custom_circle);

    // Set up the color of the Circle
    int index = cursor.getColumnIndex("Color");
    String colorString = "#" + cursor.getString(index);
    int color = Color.parseColor(colorString);
    circle.setFillColor(color);        

    // Set up the layout of the circle
    index = cursor.getColumnIndex("count");
    int totalCount = cursor.getInt(index);
    if (totalCount > 0)
    {
        circle.setFillInCircle(true);
    }
    else
    {
        circle.setFillInCircle(false);
    }
}

这些组合解决了这个问题。