はじめに
今回作りたいやつはこんなやつ。
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()
}
}
最後に
いかがでしょうか?
皆様もよきアニメーションライフを。