공감 및 댓글은 포스팅 하는데 아주아주 큰 힘이 됩니다!! 포스팅 내용이 찾아주신 분들께 도움이 되길 바라며 더 깔끔하고 좋은 포스팅을 만들어 나가겠습니다^^
|
이번 포스팅에서는 안드로이드의 이미지 뷰를 동적으로 회전시키는 방법에
대해서 포스팅합니다.
이미지 뷰를 정해진 각도만큼 변화를 주는 건 쉽습니다.
하지만 내가 터치를 해서 원하는 각도만큼 동적으로 변화를 주는 방법은
어렵진 않지만 약간에 코드를 작성해야 합니다.
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);
}
}
동적으로 이미지 회전하는 방법 어렵지 않죠?
조금만 응용한다면 여러 곳에 적용해볼 수 있겠습니다.
예를 들면 칠교 놀이같은 곳에요 ㅎㅎ
끝!
이상입니다. 감사합니다.
'안드로이드' 카테고리의 다른 글
안드로이드 Lottie 로티 애니메이션 사용하기. (0) | 2019.03.07 |
---|---|
안드로이드 View.VISIBLE, View.INVISIBLE, View.GONE 차이 (0) | 2019.03.05 |
안드로이드 Number picker 소프트키 안 뜨게 하게 disable soft keyboard (0) | 2019.02.19 |
안드로이드 NumberPicker 텍스트 색상, 크기 변경하기. how to change text size and text color of NumberPicker (0) | 2019.02.19 |
안드로이드 슬라이드 퍼즐 게임을 만들어 보았습니다. Android Slide puzzle game. (0) | 2019.02.18 |