当屏幕上有ActionBar时,为什么我的ViewGroup绘制不正确?

时间:2011-12-13 22:23:53

标签: android android-layout android-view

自从我开始尝试将ActionBar添加到我的Activity中以来,我一直在试图理解为什么我的ViewGroup实现出现故障。

我有一个自定义ViewGroup,它根据与视图当前宽度和高度相关的比率布局一组视图。 ViewGroup实现的布局算法有点像绝对布局,但它取代了绝对坐标,它采用相对于ViewGroup的宽度和高度的坐标。

我几乎忽略了布局的onMeasure传递,因为我只是想告诉孩子他们的尺寸是什么。

onLayout执行以下操作:

@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom)
{
    if (isInEditMode()) return;

    int height = getHeight();
    int width = getWidth();

    for (int i = 0; i < getChildCount(); i++)
    {
        View child = getChildAt(i);
        ImageCell cell = cells.get(i);

        int l = (int)(cell.getX0() * width);
        int t = (int)(height - (cell.getY1() * height));
        int r = (int)(cell.getX1() * width);
        int b = (int)(height - (cell.getY0() * height));

        child.layout(l, t, r, b);

        child.setBackgroundColor(0xFFFF0000);
    }
}

不幸的是,设置为我自定义ViewGroup的子视图的视图无法正确绘制自己。这些视图是简单的位图绘制视图,但位图可能会应用缩放和转换。我的视图onDraw()编写如下:

@Override
public void onDraw(Canvas canvas) 
{

    if (canvasMatrix == null) 
    {
        canvasMatrix = new Matrix();
    }

    canvasMatrix.reset();
    canvasMatrix.setScale(scaleX, scaleY);
    canvasMatrix.postTranslate(getLeft() + translationX, getTop() + translationY);
    canvas.setMatrix(canvasMatrix);

    synchronized (renderBuffer) 
    {
        /**
         * We need to offset the renderBuffer, the scaling is done by the matrix
         * on the canvas.
         */

         canvas.drawBitmap(renderBuffer, offsetX, offsetY, null);

    }
}

我正在设置一个矩阵,根据需要显示的图像的比例和平移,将缩放和平移应用到画布。然后使用指定的x和y偏移在画布上绘制图像。

似乎正在发生的事情是位图被绘制在ActionBar下面,在屏幕底部留下了一个很大的空间,没有绘制。如果我向offsetY添加一个常数因子,可以使位图在屏幕上的正确位置绘制(取决于设备的旋转)。但我不确定应该在何处计算这个常数因子。

我对Android绘图知之甚少。我原本期望Canvas相对于屏幕上的视图位置,这样如果我在(0,0)绘画,绘画将出现在视图的原点,而不是屏幕的原点。

Strange Painting Issue Example

所以这张图片就是我所看到的一个例子。底部的红色区域是子视图中未由drawBitmap绘制的部分。

知道我在这里做错了什么吗?如果视图是全屏的,那么一切都很好,但是使用ActionBar,我没有给出包含ActionBar大小的坐标,所以我似乎在它下面绘画。

1 个答案:

答案 0 :(得分:1)

你的问题在这里:canvas.setMatrix(canvasMatrix);

通过调用此方法,您可以破坏应用于Canvas的整个变换。整个窗口都有一个Canvas,因此您要删除应用于ActionBar高度偏移的变换。

您还应始终在Views上调用measure()。一些观点期望此调用正常工作。