안드로이드

안드로이드 이미지뷰 동적으로 회전시키기 With RotateAnimation and extends AppCompatImageView

알통몬_ 2019. 2. 25. 11:50
반응형


공감 및 댓글은 포스팅 하는데

 아주아주 큰 힘이 됩니다!!

포스팅 내용이 찾아주신 분들께 

도움이 되길 바라며

더 깔끔하고 좋은 포스팅을 

만들어 나가겠습니다^^

 


이번 포스팅에서는 안드로이드의 이미지 뷰를 동적으로 회전시키는 방법에 

대해서 포스팅합니다.


이미지 뷰를 정해진 각도만큼 변화를 주는 건 쉽습니다.

하지만 내가 터치를 해서 원하는 각도만큼 동적으로 변화를 주는 방법은

어렵진 않지만 약간에 코드를 작성해야 합니다.


1. AppCompatImageView 를 상속받는 RotatableImgView

package al.tong.mon.trangram;

import android.content.Context;
import android.support.v7.widget.AppCompatImageView;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.RotateAnimation;

public class RotatableImgView extends AppCompatImageView {

private double mCurrAngle = 0;
private double mAddAngle = 0;
private double finalAngle = 0;

public RotatableImgView(Context context) {
super(context);
}

public RotatableImgView(Context context, AttributeSet attrs) {
super(context, attrs);
}

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

@Override
public boolean performClick() {
return super.performClick();
}

@Override
public boolean onTouchEvent(MotionEvent evt) {

final float centerW = (float) getWidth() / 2;
final float centerH = (float) getHeight() / 2;
final float x = evt.getX();
final float y = evt.getY();

int action = evt.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
mCurrAngle = Math.toDegrees(Math.atan2(centerH - y, x - centerW));
//mCurrAngle = Math.toDegrees(Math.atan2(centerW - x, y - centerH));
break;
case MotionEvent.ACTION_MOVE:
double mPrevAngle = mCurrAngle;
mCurrAngle = Math.toDegrees(Math.atan2(centerH - y, x - centerW));
//mCurrAngle = Math.toDegrees(Math.atan2(centerW - x, y - centerH));
finalAngle = (mAddAngle + mCurrAngle) - mPrevAngle;
animate(this, mAddAngle, finalAngle);
mAddAngle += mCurrAngle - mPrevAngle;
break;
case MotionEvent.ACTION_UP:
performClick();
break;
}

return true;
}

private void animate(View view, double fromDegree, double toDegree) {
final RotateAnimation animation = new RotateAnimation((float) fromDegree, (float) toDegree,
RotateAnimation.RELATIVE_TO_SELF, 0.5f,
RotateAnimation.RELATIVE_TO_SELF, 0.5f);
animation.setDuration(0);
animation.setFillAfter(true);
view.startAnimation(animation);
}

}

위 코드대로 따라하게 되면 손쉽게 이미지를 원하는 만큼 회전시킬 수 있습니다.

그런데 이상한 점이 발견되는데요. 바로 내가 터치하여 이동하는 반대방향으로

이미지가 회전된다는 점입니다.

Math.atan2(double y, double x) 를 보면 y값을 앞에 주고, x 값을 뒤에

주라고 되어있어서 그대로 했기 때문입니다.

원하는 방향으로 회전시키려면, 주석처리 된 코드처럼 x를 앞에 y를 뒤에 주면 됩니다.

mCurrAngle = Math.toDegrees(Math.atan2(centerH - y, x - centerW)

->

mCurrAngle = Math.toDegrees(Math.atan2(centerW - x, y 

만약 원하는 각도가 아닌 특정 각도 씩만(e.g. 45도, 90도, 135도, 180도, 225도, 270도, 315도, 360도) 회전시키고 싶다면 코드를 아래처럼 추가하면 됩니다.

package al.tong.mon.trangram;

import android.content.Context;
import android.support.v7.widget.AppCompatImageView;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.RotateAnimation;

public class RotatableImgView extends AppCompatImageView {

private double mCurrAngle = 0;
private double mAddAngle = 0;
private double finalAngle = 0;

private final double A_45_ANGLE = 45;

public RotatableImgView(Context context) {
super(context);
}

public RotatableImgView(Context context, AttributeSet attrs) {
super(context, attrs);
}

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

@Override
public boolean performClick() {
return super.performClick();
}

@Override
public boolean onTouchEvent(MotionEvent evt) {

final float centerW = (float) getWidth() / 2;
final float centerH = (float) getHeight() / 2;
final float x = evt.getX();
final float y = evt.getY();

int action = evt.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
mCurrAngle = Math.toDegrees(Math.atan2(centerH - y, x - centerW));
//mCurrAngle = Math.toDegrees(Math.atan2(centerW - x, y - centerH));
break;
case MotionEvent.ACTION_MOVE:
double mPrevAngle = mCurrAngle;
mCurrAngle = Math.toDegrees(Math.atan2(centerH - y, x - centerW));
//mCurrAngle = Math.toDegrees(Math.atan2(centerW - x, y - centerH));
finalAngle = (mAddAngle + mCurrAngle) - mPrevAngle;
animate(this, mAddAngle, finalAngle);
mAddAngle += mCurrAngle - mPrevAngle;
break;
case MotionEvent.ACTION_UP:
double desAngle;
if (finalAngle % A_45_ANGLE >= A_45_ANGLE) {
desAngle = finalAngle;
} else {
desAngle = finalAngle - (finalAngle % A_45_ANGLE);
}
animate(this, mAddAngle, desAngle);
performClick();
break;
}

return true;
}

private void animate(View view, double fromDegree, double toDegree) {
final RotateAnimation animation = new RotateAnimation((float) fromDegree, (float) toDegree,
RotateAnimation.RELATIVE_TO_SELF, 0.5f,
RotateAnimation.RELATIVE_TO_SELF, 0.5f);
animation.setDuration(0);
animation.setFillAfter(true);
view.startAnimation(animation);
}

}

동적으로 이미지 회전하는 방법 어렵지 않죠?

조금만 응용한다면 여러 곳에 적용해볼 수 있겠습니다.

예를 들면 칠교 놀이같은 곳에요 ㅎㅎ

끝!

이상입니다. 감사합니다.

반응형