【问题标题】:Change coordinates of RectF after canvas rotate画布旋转后更改 RectF 的坐标
【发布时间】:2020-01-23 18:02:50
【问题描述】:

我使用此代码垂直绘制文本。

RectF rectF2 = new RectF();
matrix.mapRect(rectF2, bounds);
canvas.save();
canvas.rotate(90, rectF2.right, rectF2.top);
canvas.drawText(text, rectF2.left, rectF2.bottom, mTextPaint);
canvas.restore();

这很好用,但我也想更改坐标。因为后来我点击对象并进行拖放。

现在的问题是,如下图所示,坐标被绘制为矩形。所以当我点击那个矩形区域时,只能在画布上移动文本。

所以我想在旋转画布时也旋转原始坐标。我试过matrix.setRotate 但我无法实现我想要的。

【问题讨论】:

  • 代码here 可以满足您的需求。它将文本旋转 90 度并移动边界以匹配文本。它不处理选取框滚动以及TextView 的其他一些更高级的方面。 This project 是另一种使用路径的替代方法。
  • 我想用矩阵做运算。所以我会保存矩阵值以备后用。
  • 我认为可能是这样。虽然视图负责测量自身,但 ViewGroup 根据 ViewGroup 的规则定位视图。 (您没有提及您正在使用哪个 ViewGroup。)您可能可以通过在自定义视图中覆盖 layout() 并在此处应用矩阵值来更改边界,确定新边界并调用通过超级。另一种可能性是创建一个矩阵感知的自定义 ViewGroup。
  • 你想画一个旋转的矩形吗?或者您想知道用户何时点击文本?
  • @Android_Developer 我想两者都做。

标签: android android-canvas


【解决方案1】:

在 onDraw() 中,您可以使用矩阵变换画布。 而在 onTouch() 中,您可以使用矩阵求逆转换回屏幕坐标。

private static class MyView extends View {

    private final Paint texPaint = new Paint(){{
        setTextSize(60);
        setColor(Color.BLACK);
    }};

    private final Paint rectPaint = new Paint(){{
        setStrokeWidth(20);
        setColor(Color.RED);
        setStyle(Paint.Style.STROKE);
    }};

    private final Matrix matrix = new Matrix();

    private final RectF rect = new RectF(0, 0, 400, 150);

    public MyView(Context context) {
        super(context);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        matrix.reset();
        matrix.postRotate(45);
        matrix.postScale(1.5f, 1.5f, 0, 0);
        matrix.postTranslate(w/2, h/2);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.save();
        canvas.concat(matrix);
        canvas.drawRect(rect, rectPaint);
        //Bottom line of the drawn text is at y, if you want the text to inside the rect
        // increase the y by the text height, textHeight is the textSize
        canvas.drawText("SomeText", 0, texPaint.getTextSize(), texPaint);
        canvas.restore();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getActionMasked() == MotionEvent.ACTION_UP) {
            float x = event.getX();
            float y = event.getY();
            Toast.makeText(getContext(), isInsideRegion(x, y) ? "Inside" : "Outside", Toast.LENGTH_SHORT).show();
        }
        return true;
    }

    private boolean isInsideRegion(float x, float y) {
        Matrix invertedMatrix = new Matrix();
        if (!matrix.invert(invertedMatrix)) {
            throw new RuntimeException("Matrix can't be inverted");
        }
        float[] point = {x, y};
        invertedMatrix.mapPoints(point);
        return rect.contains(point[0], point[1]);
    }

}

【讨论】:

  • 谢谢,我希望这行得通,顺便说一下,你能解释一下为什么我们需要做matrix.postScale(1.5f, 1.5f, 0, 0); 以及什么是 1.5f?
  • 这只是一个例子,它会使矩形变大50%。如果你只需要轮换,则不需要包含它。
  • 由于我没有对其进行测试,因此我会将赏金添加到此答案中,因为我希望这可行。
【解决方案2】:

好吧,如果你想在这个视图中拖动对象,你可能需要创建 ViewGroup 并将对象放置为视图。因为您在画布上绘制的所有对象都无法点击并拖动它们。

您可以旋转、平移和调整视图大小,还可以拦截它们上的触摸事件以执行拖动

您的解决方案仅适用于带有文本的图像,如果我理解正确,您将无法使用它们来做您想做的事情

【讨论】:

  • 不,我们可以使用矩阵进行旋转、平移和调整大小。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-08-12
  • 2013-01-09
  • 2011-10-15
  • 1970-01-01
  • 2010-09-20
  • 1970-01-01
  • 2011-08-31
相关资源
最近更新 更多