Android,如何围绕一个固定点旋转箭头(图像)?

8
我有一张箭头图片,我想让它从0度旋转到180度(就像仪表盘上的指针)。箭头的一个点固定在屏幕中央和底部,箭头头部应该移动。箭头的长度是固定的(它是图像)。同时我有两个按钮,当按下左按钮时箭头向左转,按下右按钮时箭头向右转。
这个过程的逻辑是什么? enter image description here

使用矩阵来进行旋转。 - Pointer Null
1
Android如何在中心点旋转位图 - Ron
我建议您使用@Emiam的答案,这不会像矩阵一样使用CPU。 - Mohammad Ersan
5个回答

5

如果你使用画布来绘制(在你的情况下应该这样做),这实际上非常简单。

假设你知道图像应该旋转的点的坐标,那么可以像这样操作:

private void doDraw(Canvas canvas) {
canvas.save();
float px = ...;
float py = ...;
canvas.rotate(degrees, px, py);
arrow.draw(canvas);
canvas.restore();
}

degrees将是一个整数值,当用户点击左右按钮时,您需要对其进行增加/减少。canvas.rotate会处理其余部分!


这对我完全没有用(没有旋转,也没有输出)。我想知道是否是我的XML设置的问题..? - MSpeed

2

你需要在安卓平台下使用3D旋转完成动画,并尝试使用矩阵旋转...我已经有了相应的位图代码。

Bitmap bmp=BitmapFactory.decodeResource(getResources(), R.drawable.bar);
                Matrix mtx = new Matrix();
  mtx.postRotate(180);   // rotating 180 degrees clockwise
  Bitmap rotatedBMP = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth() ,bmp.getHeight() , mtx, true);  // creating the bitmap image with new angle

还要检查这个

http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/animation/Rotate3dAnimation.html


这不是一个好的策略,因为Bitmap.createBitmap方法非常缓慢,每帧都这样做会降低FPS率。 - Emir Kuljanin

2
所以有一个简短的答案和一个长的答案。
简短的答案是,位图和画布的旋转是一种常见的函数,通常称为“旋转”,通常以其围绕旋转的点为参数。
更长的答案是,所有的二维和三维图形都归结为矩阵代数的技巧。对于每个点: new_x = factor_1 * old_x + factor_2 * old_y + factor_3 ...
这些因素在矩阵中非常好用,这也是为什么矩阵变换变得如此流行的原因。有一种很酷的技巧,可以将变换链接在一起,这样你就可以将问题陈述为“取旧画布,将其移动到触摸点处,旋转它,然后将其移回到触摸点处。”或者Matrix m = new Matrix().postTranslate(-touch_x, -touch_y).postRotate(360/20).postTranslate(touch_x, touch_y)表示每次旋转1/20圆。然后,将矩阵传递给任何需要“变换”矩阵的函数。
很酷的事情是,你只需计算该矩阵一次,然后对每个点使用相同的4次乘法和一堆加法。实际上,这种情况非常普遍,视频卡和英特尔指令集都在硬件中执行这些操作。你也可以再次将结果图像乘以相同的矩阵来得到下一个图像。
现在,如果您真的想知道如何使用没有内存的超快速汇编代码来进行此操作,那么技巧是选择旋转和误差较小的链条,其中您不需要缓冲区。例如,简单的90度旋转首先会交换四个角落,然后会交换(左上角+1向左移到右上角+1向下移到右下角-1向左移到左下角-1向下,然后回到左上角+1)。这些技巧通常只在内存限制的情况下才有意义。
信息太多了,请告诉我们更多关于您的问题。

1
ImageView arrow = findViewById(/* id of your arrow */);
int width = arrow.getWidth();
int height = arrow.getHeight();
newAngle = /* init it by needed angle */;
RotateAnimation animation = new RotateAnimation(oldAngle, newAngle, width / 2, height);
oldAngle = newAngle;
animation.setDuration(200); // you may  set another duration
animation.setFillAfter(true);
arrow.startAnimation(animation);

祝你好运!


0

我看到了this的例子,然后我进行了一些调整,使其更或多或少地符合您的需求,请查看示例以更好地理解我的代码 :)


import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.os.Bundle;
import android.widget.ImageView;
import android.widget.SeekBar;

public class TesteRotateActivity extends Activity implements
    SeekBar.OnSeekBarChangeListener {

private ImageView myImageView;
private SeekBar seekbarRotate;
private float curScale = 1F;
private float curRotate = 0F;
private Bitmap bitmap;
private int bmpHeight;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    myImageView = (ImageView) findViewById(R.id.imageview);
    seekbarRotate = (SeekBar) findViewById(R.id.rotate);
    bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.teste);//here you insert your image
    bmpHeight = bitmap.getHeight();
    drawMatrix();
    seekbarRotate.setOnSeekBarChangeListener(this);
}

private void drawMatrix() {
    Matrix matrix = new Matrix();
    Matrix matrixb = new Matrix();
    Matrix matrixc = new Matrix();
    matrix.postScale(curScale, curScale);
    matrixb.setRotate(curRotate, 100, bmpHeight);
    matrixc.setTranslate(100, 0);
    matrix.setConcat(matrixb, matrixc);
    Bitmap targetBitmap = Bitmap.createBitmap(200, bmpHeight,
            bitmap.getConfig());
    Canvas canvas = new Canvas(targetBitmap);
    canvas.drawBitmap(bitmap, matrix, new Paint());
    myImageView.setImageBitmap(targetBitmap);
}

@Override
public void onProgressChanged(SeekBar seekBar, int progress,
        boolean fromUser) {
    curRotate = (float) progress;
    drawMatrix();
}

@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}

@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}

}

主要的 XML

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >

<TextView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="@string/app_name" />

<SeekBar
    android:id="@+id/rotate"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_margin="5px"
    android:max="360"
    android:progress="0" />

<ImageView
    android:id="@+id/imageview"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:scaleType="center" />

</LinearLayout>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接