得到四个坐标的矩形,画布android [英] get four co-ordinates of rectangle, canvas android

查看:979
本文介绍了得到四个坐标的矩形,画布android的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想做一个自定义视图,我正在加载位图有黑色边框和右|顶端有关闭按钮

Hi I want to make an custom view in that I am loading bitmap which has black border and right|top side there is close button

所以,当用户按应该删除该图像的关闭按钮

so when ever user press that close button that image should be removed

用于绘制这样的代码

public void draw(Canvas canvas) {
        canvas.save();

        float dx = (mMaxX + mMinX) / 2;
        float dy = (mMaxY + mMinY) / 2;

        mDrawable.setBounds((int) mMinX, (int) mMinY, (int) mMaxX, (int) mMaxY);

        canvas.translate(dx, dy);
        float rotation = mAngle * 180.0f / (float) Math.PI;
        canvas.rotate(rotation);
        canvas.translate(-dx, -dy);

        canvas.drawRect(mMinX - 10, mMinY - 10, mMaxX + 10, mMaxY + 10,
                paintBoundry);

        mDrawable.draw(canvas);
        canvas.drawCircle(mMaxX, mMinY, (mMaxX - mMinX) / 8, paintBoundry);

        canvas.restore();
    }



现在我的问题是当我旋转图像时,RED-Close按钮也会移动

Now my question is when I rotate image that RED-Close button will also moved

我想要获得RED-CIRCLE的坐标,或者您可以说矩形的第二个角坐标

我已查看以下链接,但无法取得成功

I have checked below link but could not get success

使用Matrix旋转后获取坐标的新位置

推荐答案

由于你已经有关于旋转的信息,这是好的。您现在需要做的是将旋转矩阵应用到您圈子的原始中心点(如原来,我指的是已经翻译的点,它的旋转角度是0°...你有你的代码中的信息)。从我向您提供的网页中可以看出,获取当前 x y 值的方程式如下:

Since you already have the information about the rotation, that is good. All you need to do now is apply rotation matrix to the original center point of your circle (as original, I am referring to the point that is already translated and it's rotation angle is 0°... you have that information in your code). As you can see from the webpage I provided you, the equation to get current x and y values would be:

x_new = x_original * Math.cos(mAngle) - y_original * Math.sin(mAngle);
y_new = x_original * Math.sin(mAngle) + y_original * Math.cos(mAngle);

注意: sin cos 函数采用 RADians 中的角度参数。正如我所见,您自己正在进行一些转换,您可以使用 Math.toDegrees(double radians) Math.toRadians(double degrees)

Note: sin and cos functions take an angular parameter that is in RADians. As I can see you were doing some converting on your own, you can use Math.toDegrees(double radians) and Math.toRadians(double degrees)

如果您需要,可以对其他三个点使用相同的原则。

You can use the same principle for the other three points if you need them.

编辑:解释您的代码有什么问题并粘贴了一个简单的解决方案

下载源此处


  • 画布以顺时针方向旋转对象,这与数学定义旋转的方向相反。 (如果你看到这一点,知道这样做的家伙,给他一个在我的名字的脸)。要解决此问题,您必须使用负旋转角度。

  • 您正在将视点的中心旋转,但是您正在Android的坐标系中使用触摸值。

这意味着如果从坐标系中转换一个点0至1,您将使用方程

Meaning that if you convert a point from the coordinate system 0 to 1 you would use equations

x1 = x0 - view_size / 2

y1 = y0 + view_size / 2

这是承诺的代码。首先创建名为 RotationSquare的自定义视图

Here is the promised code. First create a custom view named RotationSquare

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast;


public class RotationSquare extends View {


    private int squareBorderColor = 0xFF000000; // black
    private int innerCircleColor = 0xFFFF0000; // red
    private int outerCircleColor = 0xFF000000; // black

    private Paint squarePaint, innerCirclePaint, outerCirclePaint;
    private RectF squareRect;

    private int measuredDimenson;

    private float rotation = 0;

    // Circle parameters that should be remembered
    private float innerRadius, outerRadius, centerX, centerY;
    boolean touchedInsideCircle;


    public RotationSquare(Context context) {
        super(context);
        init(context, null, 0);
    }

    public RotationSquare(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs, 0);
    }

    public RotationSquare(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs, defStyleAttr);
    }

    private void init(Context context, AttributeSet attributeSet, int defStyle) {


        squareRect = new RectF();

        squarePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        squarePaint.setColor(squareBorderColor);
        squarePaint.setStyle(Paint.Style.STROKE);

        innerCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        innerCirclePaint.setColor(innerCircleColor);
        innerCirclePaint.setStyle(Paint.Style.FILL);

        outerCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        outerCirclePaint.setColor(outerCircleColor);
        outerCirclePaint.setStyle(Paint.Style.FILL);


    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int measuredHeight = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
        int measuredWidth = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);

        // Make a square
        measuredDimenson = Math.min(measuredHeight, measuredWidth);


        squareRect.set(0.25f * measuredDimenson, 0.25f * measuredDimenson, 0.85f * measuredDimenson, 0.85f * measuredDimenson);
        squarePaint.setStrokeWidth(0.025f * measuredDimenson);

        centerX = squareRect.right;
        centerY = squareRect.top;
        innerRadius = 0.07f * measuredDimenson;
        outerRadius = 0.08f * measuredDimenson;


        setMeasuredDimension((int) (measuredDimenson * 1f), (int) (measuredDimenson * 1f));
    }

    @Override
    protected void onDraw(Canvas canvas) {

        if (measuredDimenson <= 0) {
            return;
        }

        canvas.save(Canvas.MATRIX_SAVE_FLAG);

        canvas.rotate(rotation, measuredDimenson / 2, measuredDimenson / 2);

        canvas.drawCircle(centerX, centerY, outerRadius, outerCirclePaint);
        canvas.drawCircle(centerX, centerY, innerRadius, innerCirclePaint);
        canvas.drawRect(squareRect, squarePaint);
        canvas.restore();

    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float x = event.getX(0);
        float y = event.getY(0);
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                touchedInsideCircle = isTouchInsideCircle(x, y);
                return true;
            case MotionEvent.ACTION_MOVE:
                return true;
            case MotionEvent.ACTION_UP:
                if (touchedInsideCircle && isTouchInsideCircle(x, y)) {
                    Toast.makeText(getContext(), "Clicked the circle", Toast.LENGTH_SHORT).show();
                }
                return true;
            default:
                return super.onTouchEvent(event);
        }

    }

    public void setRotation(int rotation) {
        this.rotation = rotation;
        invalidate();
    }


    private boolean isTouchInsideCircle(float x, float y) {
        double angleRad = Math.toRadians(rotation);

        // Convert to the centered coordinate system
        double centerXConverted = centerX - measuredDimenson / 2;
        double centerYConverted = -centerY + measuredDimenson / 2;

        // Use the negative angle
        double currentCenterX = centerXConverted * Math.cos(-angleRad) - centerYConverted * Math.sin(-angleRad);
        double currentCenterY = centerXConverted * Math.sin(-angleRad) + centerYConverted * Math.cos(-angleRad);

        // Convert to the centered coordinate system
        x = x - measuredDimenson / 2;
        y = -y + measuredDimenson / 2;

        double squareRadius = outerRadius * outerRadius;
        double squaredXDistance = (x - currentCenterX) * (x - currentCenterX);
        double squaredYDistance = (y - currentCenterY) * (y - currentCenterY);

        return (squaredXDistance + squaredYDistance) < squareRadius;
    }
}

进行活动布局

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >

    <some.package.that.you.must.change.RotationSquare
        android:id="@+id/rotatingSquare"
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:layout_centerInParent="true"/>

    <SeekBar
        android:id="@+id/seekBar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="50dp"
        android:max="360"/>

    <TextView
        android:id="@+id/tvRotation"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/seekBar"
        android:gravity="center_horizontal"
        android:text="Rotation: 0°"
        android:textSize="15sp"/>

</RelativeLayout>

并且活动

public class MainActivity extends AppCompatActivity implements SeekBar.OnSeekBarChangeListener {

    private SeekBar seekBar;
    private RotationSquare rotationSquare;
    private TextView tvRotation;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        rotationSquare = (RotationSquare) findViewById(R.id.rotatingSquare);
        seekBar = (SeekBar) findViewById(R.id.seekBar);
        seekBar.setOnSeekBarChangeListener(this);

        tvRotation = (TextView) findViewById(R.id.tvRotation);
    }

    @Override
    public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
        rotationSquare.setRotation(i);
        tvRotation.setText("Rotation: " + i + "°");
    }

    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {

    }

    @Override
    public void onStopTrackingTouch(SeekBar seekBar) {

    }
}

这是最终的结果。


Here is the final result.

希望我不怕数学和这些方程:/

Hope I didn't scare you off with the math and these equations :/

这篇关于得到四个坐标的矩形,画布android的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆