嗨,我想做一个自定义的视图,因为我正在加载位图,它有黑色的边框,右上方有关闭按钮
因此当用户按下关闭按钮时,该图像应被移除
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();
}
我已经检查了下面的链接,但无法成功
利用矩阵得到旋转后坐标的新位置
既然你已经有了关于旋转的信息,那就好了。现在您需要做的是将旋转矩阵应用到圆的原始中心点(正如原始的,我指的是已经平移的点,它的旋转角度是0°……您的代码中有这些信息)。从我提供的网页中可以看到,得到当前x和y值的公式如下:
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
函数采用以弧度为单位的角度参数。正如我所看到的,您正在自己进行一些转换,您可以使用Math.Todegrees(双弧度)和Math.Toradians(双度)
如果你需要的话,你可以对其他三点使用同样的原则。
这意味着如果您将一个点从坐标系0转换为1,您将使用等式
x1=x0-view_size/2
y1=-y0+view_size/2
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) {
}
}
希望我没有用数学和这些方程式把你吓跑:/
如何获得旋转矩形的角坐标(以矩形为中心)? 我已经尝试了以下链接中的所有解决方案,但似乎没有任何运气。 将一个点绕另一个点旋转(2D) 找到给定中心点和旋转的旋转矩形的角 https://game dev . stack exchange . com/questions/86755/how-to-calculate-corner-positions-marks-of-a-rotated-tilte
在上面的图片中,我展示了两个矩形 矩形1,其x可以从-900到13700不等,Y可以从-600到6458 矩形2,其坐标X可以从0到3000变化,而y可以从0到2000变化 同样:矩形2的起点位于左上角位置(0,0),而矩形1的起点位于左上角位置(宽度/2,高度/2)。 我需要做的是:使用缩放或平移将矩形1的点转换为矩形2的点。 那么,为了将矩形1的坐标转换为矩形2的坐标,< code>x和< c
我有一个非常大的矩形(100,000x100,000),我试图在上面随机放置许多不同大小的圆。我目前的解决方案是将以前使用的所有坐标对存储在一个地图中,然后随机生成一个新的对,并检查它是否存在于地图中。 因为我生成了很多坐标,所以这个方法会变得有点慢。有没有一个更好,最重要的是更快的方法来得到矩形上的随机坐标,也许也有一个方法来得到它们而不是圆重叠?
我需要点子,这不是家庭作业...... 我有下面的矩阵,我如何获得重复数字的坐标, 重复项[[[0,0],[1,0],[2,0],[0,1],[0,1],[0,2],[1,2],[1,3],[2,2]],[[0,3],[0,4],.........] 第1组,分离2组,分离3组,仅2组 重复项[[[0,0],[1,0],[2,0],[0,1],[0,2],[1,2],[1,3],[2,2]],[[
我应该自己写方法吗?尽管我害怕不能解释一些事情,因为我的数学已经生疏了。或者我能为Java找到一个现成的实现吗?我有谷歌地图sdk在我的项目,但我找不到任何有用的东西。
我试图创建一个画布,在其中我们可以绘制直线和矩形使用鼠标事件的功能选择的输入。 我将mousedown、mousemove和mouseup事件侦听器附加到画布DOM,并在选择行输入或矩形输入时使用适当的函数 但它什么也没有画出来。 null null