根据父视图的位置渲染位图

时间:2018-07-17 09:42:09

标签: android scale android-canvas android-view android-bitmap

我正在尝试制作一个简单的图像编辑器。一开始,我认为将视图状态另存为Bitmap是一个好主意,但是事实证明,屏幕分辨率范围很广,并且会导致巨大的质量(和内存使用)波动。

现在,我正在尝试制作一个模块,以将视图状态转换为所需的分辨率。

在下面的代码中,我试图重新创建画布中视图的当前状态:

    Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.id.test_1_1);
    bitmap = Bitmap.createScaledBitmap(bitmap, parentView.getMeasuredWidth(), parentView.getMeasuredHeight(), true);

    Canvas canvas = new Canvas(bitmap);
    Paint paint = new Paint();
    for (View rootView : addedViews) {
        ImageView imageView = rootView.findViewById(R.id.sticker);

        float[] viewPosition = new float[2];
        transformToAncestor(viewPosition, parentView, imageView);

        Bitmap originalBitmap = ((BitmapDrawable) imageView.getDrawable()).getBitmap();
        Matrix adjustMatrix = new Matrix();
        adjustMatrix.postTranslate(viewPosition[0], viewPosition[1]);
        adjustMatrix.postScale(
                rootView.getScaleX(),
                rootView.getScaleY(),
                rootView.getWidth() / 2,
                rootView.getHeight() / 2);
        adjustMatrix.postRotate(rootView.getRotation(),
                rootView.getWidth() / 2,
                rootView.getHeight() / 2);

        canvas.drawBitmap(originalBitmap, adjustMatrix, paint);
    }

transformToAncestor函数来自here

public static void transformToAncestor(float[] point, final View ancestor, final View descendant) {
    final float scrollX = descendant.getScrollX();
    final float scrollY = descendant.getScrollY();
    final float left = descendant.getLeft();
    final float top = descendant.getTop();
    final float px = descendant.getPivotX();
    final float py = descendant.getPivotY();
    final float tx = descendant.getTranslationX();
    final float ty = descendant.getTranslationY();
    final float sx = descendant.getScaleX();
    final float sy = descendant.getScaleY();

    point[0] = left + px + (point[0] - px) * sx + tx - scrollX;
    point[1] = top + py + (point[1] - py) * sy + ty - scrollY;

    ViewParent parent = descendant.getParent();
    if (descendant != ancestor && parent != ancestor && parent instanceof View) {
        transformToAncestor(point, ancestor, (View) parent);
    }
}

(作者写了一条便条,即他的函数不支持旋转,但是我的示例中旋转不多,所以我认为现在不那么重要了。)

我的问题是:

Image generated via drawing views state Image generated via views to image function

通过保存父视图状态生成第一张图像。第二个是通过将视图的位置,旋转和缩放转换到画布上而生成的。 如您所见,在画布上,没有正确放置缩放比例的贴纸,但是缩放比例的位置不正确。

如何正确放置那些缩放视图?

1 个答案:

答案 0 :(得分:0)

我设法自己解决了此问题。 事实证明,我的解决方案几乎可以,但是我没有考虑到我对矩阵的操作会改变原始点的排列,所以我的

rootView.getWidth() / 2,
rootView.getHeight() / 2

在调用Matrix.postScaleMatrix.postRotation之后不再可用作视图的中心。

我想:

  • 应用比例尺,将枢轴放在左上角,
  • 应用旋转,并在视图中心旋转。

给出假设,这是工作代码:

    // setup variables for sizing and transformation
    float position[] = new float[2];
    transformToAncestor(position, rootView, imageView);
    float desiredRotation = imageView.getRotation();
    float sizeDeltaX = imageView.getMeasuredWidth() / (float) imageBitmap.getWidth();
    float sizeDeltaY = imageView.getMeasuredHeight() / (float) imageBitmap.getHeight();
    float desiredScaleX = imageView.getScaleX() * sizeDeltaX * scaleX;
    float desiredScaleY = imageView.getScaleY() * sizeDeltaY * scaleY;
    float imageViewWidth = imageView.getMeasuredWidth() * imageView.getScaleX();
    float imageViewHeight = imageView.getMeasuredHeight() * imageView.getScaleY();

    float rootViewWidth = rootView.getMeasuredWidth();
    float rootViewHeight = rootView.getMeasuredHeight();
    float percentXPos = position[0] / rootViewWidth;
    float percentYPos = position[1] / rootViewHeight;
    float percentXCenterPos = (position[0] + imageViewWidth/2)
            / rootViewWidth;
    float percentYCenterPos = (position[1] + imageViewHeight/2)
            / rootViewHeight;

    float desiredPositionX = background.getWidth() * percentXPos;
    float desiredPositionY = background.getHeight() * percentYPos;
    float desiredCenterX = background.getWidth() * percentXCenterPos;
    float desiredCenterY = background.getHeight() * percentYCenterPos;

    // apply above variables to matrix
    Matrix matrix = new Matrix();
    float[] points = new float[2];
    matrix.postTranslate(
            desiredPositionX,
            desiredPositionY);

    matrix.mapPoints(points);
    matrix.postScale(
            desiredScaleX,
            desiredScaleY,
            points[0],
            points[1]);

    matrix.postRotate(
            desiredRotation,
            desiredCenterX,
            desiredCenterY);

    // apply matrix to bitmap, then draw it on canvas
    canvas.drawBitmap(imageBitmap, matrix, paint);

如您所见,mapPoints方法是我的问题的答案-它只是在转换后 返回了点。