7
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

GoodpatchAdvent Calendar 2018

Day 18

Androidで丸いCardViewを滑らかにページ遷移させる

Last updated at Posted at 2018-12-17

この記事は Goodpatch Advent Calendar 2018 18日目の記事です。

Google I/O 2018でMaterial Themingが発表され、最近のGoogle製アプリではGoogle独自のMaterial Designを採用したアプリが増えてきましたね。

また、その影響やiOS側のトレンドの変化もあって最近では、様々なアイコンやViewの形状が丸くなってきてたように思います。
そのあたりの考察は別の記事に譲るとして、今回はAndroid開発者として、角が丸めのCardViewを実装した時に困ったことと、その対処法をご紹介します。

cardCornerRadius=16dpのCardView

まずは最近流行りの丸いCardViewを作ります。
分かりやすいようにcardCornerRadiusは16dpにしておきましょう。

<androidx.cardview.widget.CardView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:cardCornerRadius="16dp"
            app:cardElevation="1dp">

はい、できました。簡単ですね。

Transition Animationがうまくいかない

このCardViewにShared Elementsを使ったTransition Animationを付けて別のActivityに遷移させてみます。

animation10.gif
分かりやすいようにWindow Animation Scaleはx10です。

アニメーションが始まった瞬間にCardViewでClipされていた四角い画像が表に出てきているのが分かりますか?
Shared Elementを使ったときに遷移中に表示されるViewは遷移後のActivityのViewです。このためClipされていない遷移後のViewがタップ直後に表示されてしまいます。
これではせっかくのCardViewが少し残念です。

Transition中のViewのサイズに合わせてClipするradiusを変化させる

今回はCardViewの中に使うViewをpathでclipすることで滑らかにアニメーションさせるようにしてみました。
Transition Animation時にViewのサイズが変わるたびにonDrawが呼びだされるため、その時のViewの幅に合わせて少しずつRadiusが変化するようにします。

private val rootWidth = resources.displayMetrics.widthPixels
private val cornerRadius: Float = resources.getDimension(R.dimen.card_corner_radius)
private val cardSideMargin: Float = resources.getDimension(R.dimen.card_side_margin) * 2

override fun onDraw(canvas: Canvas) {
        // viewの幅に合わせてcornerRadiusを変化させる
        val radius = Math.min(cornerRadius, cornerRadius * ((rootWidth - this.width) / cardSideMargin))
        clipPath.reset()
        clipRectF.set(canvas.clipBounds)
        clipPath.addRoundRect(clipRectF, radius, radius, Path.Direction.CW)
        canvas.clipPath(clipPath)
        super.onDraw(canvas)
}

animation11.gif
いい感じになりました。(個人の感想です。

今回のすべてのサンプルはこちらです。
ymegane/CardAnimationSample | GitHub

これで週末は心置きなく映画館に行けそうです。
みなさんよいクリスマスを。

7
2
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
7
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?