LoginSignup
9
4

More than 5 years have passed since last update.

ViewFlipperでObjectAnimatorを使う

Last updated at Posted at 2019-01-22

はじめに

今回作りたいやつはこんなやつ。

ViewFlipperで表面、裏面を切り替える際、シンプルなアニメーション(ViewAnimator)ではなくObjectAnimatorのようなリッチなアニメーションを使いたい…
でもAdapterViewFlipperは実装が大変。。

実はちょっと工夫することで簡単にObjectAnimatorを使うことが出来ます。

実装

activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<ViewFlipper
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/flipper"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="500dp"
        android:padding="30dp">
    <!-- 表面のレイアウト -->
    <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="#ffaaaa">
        <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Hello World!"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintTop_toTopOf="parent"/>
    </androidx.constraintlayout.widget.ConstraintLayout>
    <!-- 裏面のレイアウト -->
    <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="#aaffaa">
        <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Hello World!の裏"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintTop_toTopOf="parent"/>
    </androidx.constraintlayout.widget.ConstraintLayout>
</ViewFlipper>
MainActivity.kt
class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // 消えるときのアニメーション
        val outRotationY = ObjectAnimator.ofFloat(flipper, "rotationY", 0f, 90f)
        // 現れるときのアニメーション
        val inRotationY = ObjectAnimator.ofFloat(flipper, "rotationY", 270f, 360f)

        outRotationY.addListener(object : AnimatorListenerAdapter() {
            override fun onAnimationEnd(animation: Animator?) {
                // 消えるアニメーションが終了したタイミングで現れるアニメーションを実行
                inRotationY.start()
                // ViewFlipperの裏面レイアウトの表示を行う
                flipper.showNext()
            }
        })

        // flipperをタップしたら消えるアニメーションを実行する
        flipper.setOnClickListener {
            outRotationY.start()
        }
    }
}

以上を実装することで最初のGifアニメが再現できます。

その他アニメーション

前述のアニメーションは上下の幅をとってしまい、見栄えが悪かったため実際のアプリではこちらのアニメーションを採用しました。よくあるカードをひっくり返すアニメーションです。

Main2Activity.kt
class Main2Activity : AppCompatActivity() {
    var isReversed = false

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        flipper.setOnClickListener {
            reverseCard(flipper, 1.0f, 0.0f, 1.0f, 1.0f)
            isReversed = true
        }
    }

    fun reverseCard(viewFlipper: ViewFlipper, vararg rotate: Float) {
        val scaleX = ObjectAnimator.ofFloat(viewFlipper, "scaleX", rotate[0], rotate[1])
        val scaleY = ObjectAnimator.ofFloat(viewFlipper, "scaleY", rotate[2], rotate[3])
        val animatorSet = AnimatorSet()
        animatorSet.interpolator = LinearInterpolator()
        animatorSet.playTogether(scaleX, scaleY)
        animatorSet.duration = 200
        animatorSet.addListener(object : AnimatorListenerAdapter() {
            override fun onAnimationEnd(animation: Animator?) {
                if (!isReversed) return

                reverseCard(viewFlipper, 0.0f, 1.0f, 1.0f, 1.0f)
                isReversed = false
                viewFlipper.showNext()
            }
        })
        animatorSet.start()
    }
}

最後に

いかがでしょうか?
皆様もよきアニメーションライフを。

9
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
4