アニメーションを使用するのが最も簡単な解決策です。独自に作成することも、複数のTranslateAnimationsと ScaleAnimationsを組み合わせて試すこともできます。
これは、スクロールビューを使用する代わりに、各番号を独自のTextViewに配置することを意味します。
次に、補間器を使用して中央への加速を制御できます。補間器は、Androidがイージングを処理する方法です。スピードアップ/スローダウン効果のためにAccelerateDecelerateInterpolatorが必要になるでしょう。
AnimationSetを使用して、同じビューに複数のアニメーションを適用できます。優れたAnimationSetをまとめる方法を見つけることは、プロジェクトの最も難しい部分です。「fill」プロパティに注意を払うようにしてください。実際、少し遊んだ後は、カスタムアニメーションは既製のものを使用するよりも簡単だと思います。
これの非常に単純なバージョンを実装する私のGitHubプロジェクトをフォークすることができます。4月17日以前は、複数の既成のアニメーションを使用していました。最新バージョンを見ると、カスタムアニメーションが表示されます。
各アニメーションのタイミングは、1つのアニメーションの期間を設定した後に自動的に処理されます。ハンドラーは、前の番号が終了した後、次の番号を呼び出します。これは、すべてを更新するためにX秒ごとに関数を呼び出す必要があるよりも少しすっきりしていると思います。
機能の概要:
- アクティビティ(CountDownActivity.java)はすべてを監視します。
- ActivitiyのレイアウトXMLには、カウントダウンを開始するために使用されるボタンがあります。
- カウントダウンが始まると、ボタンが消えます。カウントダウンが完了すると再表示されます。
- アクティビティにはハンドラー(MotionHandler.java)が含まれています。ハンドラーは、数字の移動とタイミングを制御します。
- ハンドラーはAnimationSetを使用して数値を移動します
- AnimationSetは依存関係で渡されます
- これは柔軟性のためです。別のAnimationSetを渡すだけで、数値の移動方法を変更できます
- AnimationSetは、カスタムアニメーションの
4つのアニメーションで構成されています(以下を参照)。
- AnimationSetは、共有されたAccelerateDecelerateInterpolatorを使用します。これは、適切に機能しているようです。あなた自身を書くことを含む他のオプションがあります。
- ハンドラーは遅延メッセージを使用して次の番号を開始します
- カスタムリスナーを使用してカウントダウンが行われると、ハンドラーはアクティビティに通知します(MotionHandler >> CountdownListener)
- デバイスを回転させると、カウントダウンが再開されます。
注-以前は、1つのAnimationSetで4つの既製のアニメーションを使用していましたが、1つのカスタムアニメーションのみを含むように編集しました...そのアルゴリズムを好みに合わせて調整できます。
このカスタムアニメーションは、サイクロイドを使用して数字を大きくしたり小さくしたりします。
/**
* A custom animation to move and scale the numbers.
*
*/
public class NumberAnimation extends Animation
{
final public static float MINIMUM = 3;
private int mHorizontal;
private int mScaling;
public NumberAnimation(int horizontalMovement, int scaling)
{
mHorizontal = horizontalMovement;
mScaling = scaling;
}
@Override
protected void applyTransformation(float interpolatedTime, Transformation t)
{
// Cycloid repeats every 2pi - scale interpolatedTime to that
double time = 2 * Math.PI * interpolatedTime;
// Cycloid function
float currentScale = (float) (mScaling * (1 - Math.cos(time))) + MINIMUM;
Matrix matrix = t.getMatrix();
matrix.preScale(currentScale, currentScale);
matrix.postTranslate(mHorizontal * interpolatedTime, 0);
}
}