Android, как можно повернуть стрелку (изображение) вокруг фиксированной точки? - PullRequest
8 голосов
/ 14 сентября 2011

У меня есть изображение стрелки, которое я хочу повернуть от 0 до 180 градусов (как стрелка в метре). Одна точка стрелки зафиксирована посередине и в нижней части экрана, и головка стрелки должна двигаться. Длина стрелки фиксирована (это изображение). Также у меня есть две кнопки, и я хочу, чтобы стрелка поворачивалась влево при касании кнопки влево и поворачивалась вправо при нажатии правой кнопки.

Какова логика этого процесса?

enter image description here

Ответы [ 5 ]

5 голосов
/ 01 октября 2011

Это на самом деле довольно просто, если вы используете холст для рисования (как и в вашем случае).

Учитывая, что вы знаете координаты точки, вокруг которой должно вращаться изображение, вы можете сделать это следующим образом:

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

градусов будет целочисленным значением, которое вы увеличиваете / уменьшаете, когда пользователь нажимает кнопки L или R. canvas.rotate позаботится обо всем остальном!

2 голосов
/ 05 октября 2011

Таким образом, есть короткий ответ и длинный ответ.

Короткий ответ заключается в том, что вращение растровых изображений и холстов - это обычная функция, обычно называемая «вращением» и обычно принимающая точку, вокруг которой вращается.

Более длинный ответ состоит в том, что вся 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 умножения для каждой точки икуча добавлений.На самом деле, это настолько распространено, что видеокарты и набор инструкций Intel делают это аппаратно.Вы также можете просто умножить полученное изображение снова на ту же матрицу, чтобы получить следующую.

Теперь, если вы действительно просите взломать графику, как мне сделать это в каком-то безумно быстром коде сборки безпамять, уловка состоит в том, чтобы выбирать вращения и ошибки в маленькие цепочки, где вам не нужен буфер.Например, простой поворот на 90 градусов сначала поменяет четыре угла, а затем поменяется местами (верхний левый + 1 левый переходит в верхний правый + 1 нисходящий, который переходит в нижний правый - 1 левый, который переходит в нижний левый - 1 нисходящий, которыйвозвращается в верхний левый + 1).Эти приемы обычно имеют значение только для ограничений памяти.

Слишком много информации.Расскажите подробнее о своей проблеме.

2 голосов
/ 14 сентября 2011

Вы, вероятно, должны работать с анимацией, используя трехмерное вращение в Android, и пытаться также использовать вращение матрицы ... У меня есть растровый код для этого .........

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

1 голос
/ 03 октября 2011
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 голосов
/ 22 июня 2012

я вижу этот пример, и я приспособился работать более или менее так, как вам нужно, пожалуйста, посмотрите пример для лучшего понимания моего кода:)


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>
...