- 2008-02-23 15:40
- android

前回のエントリでAndroid SDK m5-rc14対応の電子ブックリーダを公開しました。
そこで適用した3D回転エフェクトの掛け方をご紹介します。
現在表示している画面をグルっと回転させて、裏側に別の画像を表示する。
グルっと回転させて、表と裏の表示を切り替えるので、表面と裏面を準備します。
レイアウトXMLはこんな感じです。
main.xml
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/container" android:layout_width="fill_parent" android:layout_height="fill_parent"> <ImageView android:id="@+id/front" android:src="@drawable/front" android:layout_width="fill_parent" android:layout_height="fill_parent" /> <ImageView android:id="@+id/back" android:src="@drawable/back" android:layout_width="fill_parent" android:layout_height="fill_parent" android:visibility="gone" /> </FrameLayout>
FrameLayoutを回転させます。
その際にfrontとbackの表示を切り替えます。
初期状態はbackが非表示(gone)です。
public void onCreate(Bundle icicle) { super.onCreate(icicle); setContentView(R.layout.main); this.mContainer = (ViewGroup) findViewById(R.id.container); this.frontView = (ImageView) findViewById(R.id.front); this.backView = (ImageView) findViewById(R.id.back); }
これはAndroidの基本ですね。
まず表示面のまま90度回転させます。
float start = 0f; float mid = 90f; this.centerX = mContainer.getWidth() / 2.0f; this.centerY = mContainer.getHeight() / 2.0f; Rotate3dAnimation rot; rot = new Rotate3dAnimation(start, mid, centerX, centerY, depth, true); rot.setDuration(500); rot.setAnimationListener(new DisplayNextView(mid, end, depth)); mContainer.startAnimation(rot);
Rotate3dAnimationはAnimationクラスを継承した独自クラスです。
ApiDemoをそのまま使わせてもらっています。
アニメーションは、AnimationクラスのapplyTransformationメソッドが呼出されることで動作します。
void applyTransformation(float interpolatedTime, Transformation t) { ... }
interpolateTimeは0から1までの値が渡さます。
ちょっと複雑なのですが、0から1まで連続した値が渡されてapplyTransformationメソッドがよびだされ続けます。
時系列で説明するとこんな感じです。
applyTransformation(0f, t); applyTransformation(0.2f, t); applyTransformation(0.4f, t); applyTransformation(0.6f, t); applyTransformation(0.8f, t); applyTransformation(1.0f, t);
setDurationで指定した500msの間でcallされ続けます。
この例では、0.2間隔で呼出されています。この間隔を変更したい場合は、
rot.setInterpolator(new AccelerateInterpolator());
を設定します。間隔の時間を変化しながらapplyTransformationが呼出されます。
ちょっと複雑ですが、引数のinterpolatedTimeに応じて対象を移動させたり、表示角度を変化させたりすれば、アニメーションを実装できます。
回転の場合はカメラを回転させています。
Camera camera = new Camera(); camera.rotateY(degrees);
startAnimationは、名前の通りアニメーションを開始します。
DisplayNextViewはAnimation.AnimationListenerをimplementsしたクラスです。
これはアニメーションのイベントを取得できるリスナーです。
取得できるイベントは、以下の3つ。
void onAnimationEnd() void onAnimationRepeat() void onAnimationStart()
今回は0度から90度までの回転アニメーションが終わると、残りの90度から180度までを回転させます。
よってonAnimationEndイベントを利用します。
ではonAniamtionEndで残りの回転をさせます。回転処理は基本的に今までと同じです。
Rotate3dAnimationを使います。
その前に、表示面を切り替えます。表から裏面に切り替える例を示します。
this.frontView.setVisibility(View.GONE); this.backView.setVisibility(View.VISIBLE);
概要はこんな感じです。
private class DisplayNextView implements AnimationListener { public void onAnimationStart() { } public void onAnimationRepeat() { } public void onAnimationEnd() { mContainer.post(new Runnable() { frontView.setVisibility(View.GONE); backView.setVisibility(View.VISIBLE); Rotate3dAnimation rot; rot = new Rotate3dAnimation(mid, end, centerX, centerY, depth, false); rot.setDuration(500); rot.setInterpolator(new AccelerateInterpolator()); mContainer.startAnimation(rot); }); } }
以上で3次元の回転を実装できました。
動作はこういった感じです。
eclipseプロジェクトを公開します。ご参考にどうぞ。
rotation3d.zip
3Dアニメーションはテクニカルで勉強になりました。
ちょっと複雑なので、いずれ誰かが簡単なライブラリを作る気もする。
でも基礎を知っていて損は無いと思った。
イメージはDeep anatomy @kayaprajnaからお借りしました。Special Thanx!
package com.adamrocker.android.rotation3d; import android.app.Activity; import android.os.Bundle; import android.view.KeyEvent; import android.view.View; import android.view.ViewGroup; import android.view.animation.AccelerateInterpolator; import android.view.animation.Animation.AnimationListener; import android.widget.ImageView; public class Rotation3D extends Activity { private boolean isFront = true; private int DURATION = 500; private ViewGroup mContainer; private ImageView frontView, backView; private float centerX; private float centerY; /** Called when the activity is first created. */ @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); setContentView(R.layout.main); this.mContainer = (ViewGroup) findViewById(R.id.container); this.frontView = (ImageView) findViewById(R.id.front); this.backView = (ImageView) findViewById(R.id.back); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { super.onKeyDown(keyCode, event); switch (keyCode) { case KeyEvent.KEYCODE_SPACE: if (isFront) { applyRotation(0f, 90f, 180f, 0f); } else { applyRotation(180f, 270f, 360f, 0f); } break; } return false; } /* startからendまでY軸回転する */ private void applyRotation(float start, float mid, float end, float depth) { this.centerX = mContainer.getWidth() / 2.0f; this.centerY = mContainer.getHeight() / 2.0f; Rotate3dAnimation rot = new Rotate3dAnimation(start, mid, centerX, centerY, depth, true); rot.setDuration(DURATION); // rot.setInterpolator(new AccelerateInterpolator()); rot.setAnimationListener(new DisplayNextView(mid, end, depth)); mContainer.startAnimation(rot); } private class DisplayNextView implements AnimationListener { private float mid; private float end; private float depth; public DisplayNextView(float mid, float end, float depth) { this.mid = mid; this.end = end; this.depth = depth; } public void onAnimationEnd() { mContainer.post(new Runnable() { public void run() { if (isFront) { frontView.setVisibility(View.GONE); backView.setVisibility(View.VISIBLE); isFront = false; } else { frontView.setVisibility(View.VISIBLE); backView.setVisibility(View.GONE); isFront = true; } Rotate3dAnimation rot = new Rotate3dAnimation(mid, end, centerX, centerY, depth, false); rot.setDuration(DURATION); rot.setInterpolator(new AccelerateInterpolator()); mContainer.startAnimation(rot); } }); } public void onAnimationStart() {} public void onAnimationRepeat() {} } }
Comments:0
Trackbacks:1
- Trackback URL for this entry
- http://www.adamrocker.com/blog/188/android_3d_rotatoin_effect.html/trackback/
- Listed below are links to weblogs that reference
- Androidで3D回転エフェクトをかける方法 from throw Life
