【问题标题】:Android, How can I rotate an arrow (image) around a fixed point?Android,如何围绕固定点旋转箭头(图像)?
【发布时间】:2011-11-16 20:12:09
【问题描述】:

我有一个箭头图像,我想从 0 度旋转到 180 度(就像一米中的指针)。箭头的一个点固定在屏幕的中间和底部,箭头的头部应该移动。箭头的长度是固定的(它是图像)。另外我有两个按钮,我希望箭头在左键被触摸时向左转,在右键被触摸时向右转。

这个过程的逻辑是什么?

【问题讨论】:

标签: android image rotation point


【解决方案1】:

如果您使用画布进行绘图,这实际上非常简单(在您的情况下应该如此)。

鉴于您知道图像应围绕其旋转的点的坐标,您可以这样做:

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

degrees 将是一个整数值,当用户单击 L 或 R 按钮时,您可以递增/递减该值。 canvas.rotate 负责其余的工作!

【讨论】:

  • 这实际上对我根本不起作用(没有旋转,没有输出)。我想知道这是否是我的 XML 设置..?
【解决方案2】:

您必须在 android 中使用 3d 旋转来处理可能的动画,并尝试使用 Matrix Rotation ...我有这方面的位图代码.........

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 速率。
【解决方案3】:

所以有短答案和长答案。

简短的回答是位图和画布的旋转是一个常见的功能,通常称为“旋转”,通常取旋转所围绕的点。

更长的答案是所有 2D 和 3D 图形都变成了矩阵代数的技巧。对于每个点: 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)。这些技巧通常只对内存限制很重要。

信息太多了。告诉我们更多关于您的问题。

【讨论】:

    【解决方案4】:
    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);
    

    祝你好运!

    【讨论】:

      【解决方案5】:

      我看到了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) {
      }
      
      }
      

      main的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>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2023-04-07
        • 1970-01-01
        • 2022-08-24
        • 1970-01-01
        • 2013-12-18
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多