最近、とあるAndroidアプリを開発しているのですが、その中でとある画像をぐりんと
奥行き方向というか3Dというか、ぺろんと回転させるという要件がありました。
もっと分かり易く言うと、かるたとかトランプとかの裏表をひっくり返すイメージですね。
標準のアニメーションとして用意されていれば話は早かったのですが、どうやら標準ではないらしい。。
調べ方が悪いんでしょうが、なかなかわからずエラい苦労したのですが、
なんとかやり方がわかりましたのでご紹介してみます。
まず、layoutファイルです。
RelativeLayoutにImageViewを2枚重ねて置きます。
layout/front_back.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout android:id="@+id/layout" android:layout_width="fill_parent" android:layout_height="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android"> <ImageView android:id="@+id/imageViewFront" android:layout_width="fill_parent" android:layout_height="fill_parent" android:contentDescription="@string/content_description" android:scaleType="fitXY" android:src="@drawable/front"/> <ImageView android:id="@+id/imageViewBack" android:layout_width="fill_parent" android:layout_height="fill_parent" android:contentDescription="@string/content_description" android:scaleType="fitXY" android:src="@drawable/back" android:visibility="invisible"/> </RelativeLayout> |
※このとき、裏面にあたるImageViewのvisibilityは”invisible”にしておきます。
次にぺろんとさせるアニメーションのクラスです。Animationクラスを継承して作ります。
FrontBackSwitchAnimator.class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
import android.graphics.Camera; import android.graphics.Matrix; import android.view.View; import android.view.animation.AccelerateDecelerateInterpolator; import android.view.animation.Animation; import android.view.animation.Transformation; public class FrontBackSwitchAnimator extends Animation { private Camera camera; /** 表面のView*/ private View frontView; /** 裏面のView*/ private View BackView; private float centerX; private float centerY; private boolean forward = true; private boolean visibilitySwapped; public FrontBackSwitchAnimator(View frontView, View BackView, int centerX, int centerY) { this.frontView = frontView; this.BackView = BackView; this.centerX = centerX; this.centerY = centerY; setDuration(500); setFillAfter(true); setInterpolator(new AccelerateDecelerateInterpolator()); } public void reverse() { forward = false; View temp = BackView; BackView = frontView; frontView = temp; } @Override public void initialize(int width, int height, int parentWidth, int parentHeight) { super.initialize(width, height, parentWidth, parentHeight); camera = new Camera(); } @Override protected void applyTransformation(float interpolatedTime, Transformation t) { final double radians = Math.PI * interpolatedTime; float degrees = (float) (180.0 * radians / Math.PI); if (interpolatedTime >= 0.5f) { degrees -= 180.f; if (!visibilitySwapped) { frontView.setVisibility(View.GONE); BackView.setVisibility(View.VISIBLE); visibilitySwapped = true; } } if (!forward) degrees = -degrees; final Matrix matrix = t.getMatrix(); camera.save(); camera.translate(0.0f, 0.0f, (float) (150.0 * Math.sin(radians))); camera.rotateY(degrees); // ここをrotateX()にすると、縦方向に回転します camera.getMatrix(matrix); camera.restore(); matrix.preTranslate(-centerX, -centerY); matrix.postTranslate(centerX, centerY); } } |
最後に実際にこれらを使うActivityです。
FrontBackSwitchActivity.class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
import android.app.Activity; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.ImageView; import android.widget.RelativeLayout; public class FrontBackSwitchActivity extends Activity implements OnClickListener { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.front_back); } @Override public void onClick(View v) { switchFrontBackView(false); // 表から裏にひっくり返す場合 // switchFrontBackView(true); // 裏から表にひっくり返す場合 } private void switchFrontBackView(boolean isReverse) { RelativeLayout relativeLayout = (RelativeLayout) findViewById(R.id.layout); View frontView = (ImageView)findViewById(R.id.imageViewFront); View backView = (ImageView)findViewById(R.id.imageViewBack); if(frontView == null || backView == null) return; FrontBackSwitchAnimator animator = new FrontBackSwitchAnimator(frontView, backView, backView.getWidth() /2 , backView.getHeight() / 2); if(isReverse) animator.reverse(); relativeLayout.startAnimation(animator); } } |
ちょっとごちゃごちゃしていますが、まとめると、
・何らかのイベントに引っ掛けて、switchFrontBackView()を呼びだす
その際、switchFrontBackView()にbooleanを渡して、裏表のどちらにひっくり返すのかを制御しています
・switchFrontBackViewメソッド内で、表と裏のImageViewを取得し、2つのViewのvisibility切り替え時に
アニメーションを付与しています。
イメージが掴みにくいと思いますので、実際に動かして見てください。(動くと思いますので。。
元Javaプログラマ。現在はScala/PlayでWeb開発と、SwiftでiOSアプリ開発をしています。 Unitテストとか書いてる時が一番楽しかったりします。