【Android】Canvasを使ってルーレットを作る② - Animationクラスとフリックイベント -
今回は前回作成したルーレット板にアニメーションを付けてくるくる回してみる部分です。
Animationクラスを継承したArcAnimationからRouletteViewのパラメータを調整しながらonDrawを何度も呼ぶという処理です。
実装
ArcAnimationクラスのソースコード
import android.view.animation.Animation;
import android.view.animation.Transformation;
public class ArcAnimation extends Animation {
int base = 20;
int count = 0;
private MainActivity.RouletteView rouletteView;
public ArcAnimation(MainActivity.RouletteView rouletteView) {
this.rouletteView = rouletteView;
}
@Override
protected void applyTransformation(float interpolatedTime, Transformation transformation) {
count++;
int move = base - (count / 25);
if(move < 0){
move = 0;
}
rouletteView.addPos(move);
rouletteView.requestLayout();
if(move == 0){
cancel();
rouletteView.setIsAnimation(false);
}
}
}
メンバ変数のbaseはパネルを移動させる初期値です。つまりルーレット始動直後は20℃ずつ回転します。
メンバ変数のcountはアニメーションの回数です。このカウンタによりだんだんと回転速度を遅くする調整をします。
applyTransformation()がアニメーションのキモで、引数として渡されるinterpolatedTimeに0.0f-1.0fの範囲でアニメーションの進行値が入ってきます。が、今回はcountの値により制御しているので、この値は使用していません。
上記を見てもらうと分かると思いますが、25回アニメーションしたらbaseの値を少し下げたものをmoveする値としてRouletteViewにセットしています。
MainActivity.RouletteViewクラスのソースコード(変更点)
int pos;
public void addPos(int move) {
pos += move;
}
メンバ変数「pos」とposの加算メソッドを追加します。
posの値によって移動する角度を決めます。
// パネルの描画
for (int i = 0; i < num; i++) {
paint.setColor(colors[i]);
canvas.drawArc(rectF, (i * angle) + pos, angle, true, paint);
}
draArcの第一引数(開始位置)にposを加算します。
// テキストの描画
for (int j = 0; j < num; j++) {
int intTextAngle;
if(j == 0) {
intTextAngle = angle / 2 + pos;
} else{
intTextAngle = angle;
}
canvas.rotate(intTextAngle, xc, yc);
canvas.drawText(testStrings[j], xc + 100, yc + 20, textPaint);
}
テキストの方もposを加算します。ここで注意なのがposを加算するテキストは初回だけです。
MainActivityクラスのソースコード
最後にアニメーションの開始処理を作成します。
画面をフリックしたらルーレットが回るというUIにしたいと思います。
// タッチイベントを処理するためのインタフェース
private GestureDetector gestureDetector;
// タッチイベント
@Override
public boolean onTouchEvent(MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
// タッチイベントのリスナー
private final GestureDetector.SimpleOnGestureListener onGestureListener = new GestureDetector.SimpleOnGestureListener() {
// フリックイベント
@Override
public boolean onFling(MotionEvent event1, MotionEvent event2, float velocityX, float velocityY) {
if(!rouletteView.isAnimation) {
// アニメーション開始
rouletteView.setIsAnimation(true);
animation = new ArcAnimation(rouletteView);
animation.setDuration(10000);
rouletteView.startAnimation(animation);
}
return false;
}
};
フリックイベントにはSimpleOnGestureListenerを使用します。
メンバ変数のonGestureListenerにSimpleOnGestureListenerを登録しておき、ActivityのonTouchEventから呼び出すと言う流れです。
SimpleOnGestureListenerのonFling()メソッドではアニメーションクラスを生成します。
setDurationはアニメーションの時間をミリ秒でセットします。今回はルーレットが止まるまでなのでとりあえず10秒を設定しておきます。(この設定がないと動きません)
startAnimationメソッドを生成したアニメーションクラスを引数に渡して投げてやればルーレットが回転します。
実行結果
このルーレットは何回回しても一定の角度を移動したら止まりますが、applyTransformationで乱数を使って調整することで、どこで止まるか分からないドキドキルーレットができそうです。 |
サンプルアプリ
ソースコードを以下にアップしておきました。
https://github.com/s-watanabe-apps/android-rouletteまた、ここまで作成した物に少し機能を付け加えてリリースしたアプリが以下になります。
※パッケージ名が違いますが気にしないでください。
https://play.google.com/store/apps/details?id=swapp.com.roulette
コメント
コメントを投稿