炫酷的卡片動畫[譯]

我在以前翻譯的一篇文章中介紹了MotionLayout,若是你還不知道MotionLayout是什麼,先看這篇MotionLayout介紹android

今天想要介紹一個用MotionLayout實現的很是炫酷的翻頁動畫,翻譯自Mediumgit

這是效果github

可滑動的卡片

如何實現上面的卡片呢app

  • 咱們在xml中使用MotionLayout並定義了一個FrameLayout
<androidx.constraintlayout.motion.widget.MotionLayout
        android:id="@+id/motionLayout"
        app:layoutDescription="@xml/memory_curve_scene"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:motionDebug="SHOW_ALL">


        <FrameLayout
            android:id="@+id/bottomCard"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:background="@color/design_default_color_primary">
        </FrameLayout>

    </androidx.constraintlayout.motion.widget.MotionLayout>
複製代碼

注意一下這一行app:motionDebug=」SHOW_ALL」,它可讓咱們在屏幕上展現一些當前MotionLayout的一些屬性,好比progress等等。一般只會在debug模式下使用,記得app正式發佈的時候關閉它。ide

而後在MotionScene文件,也就是咱們在res/xml目錄下定義的文件中加入初始的ConstraintSetpost

<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <ConstraintSet android:id="@+id/rest">
        <Constraint
            android:id="@id/topCard"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_marginStart="50dp"
            android:layout_marginTop="50dp"
            android:layout_marginEnd="50dp"
            android:layout_marginBottom="50dp"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"/>
    </ConstraintSet>
</MotionScene>
複製代碼

讓咱們添加passlike狀態的constraintSet,當咱們徹底滑動到左邊或者右邊的時候,就處在這個狀態。動畫

<ConstraintSet android:id="@+id/pass"
        app:deriveConstraintsFrom="@id/rest">
        <Constraint
            android:id="@id/topCard"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_marginStart="50dp"
            android:layout_marginTop="20dp"
            android:layout_marginEnd="200dp"
            android:layout_marginBottom="80dp"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintWidth_percent="0.7"/>

    </ConstraintSet>

    <ConstraintSet android:id="@+id/like"
        app:deriveConstraintsFrom="@id/rest">
        <Constraint
            android:id="@id/topCard"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_marginStart="200dp"
            android:layout_marginTop="20dp"
            android:layout_marginEnd="50dp"
            android:layout_marginBottom="80dp"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintWidth_percent="0.7"/>
    </ConstraintSet>
複製代碼

passlike狀態其實就是鏡像的兩個狀態。spa

注意一下這一行app:deriveConstraintsFrom="@id/rest",這能讓該ConstraintSet自動繼承另外一個ConstraintSet的屬性,固然也能夠覆寫另外一個ConstraintSet的屬性。翻譯

如今,咱們有了三個ConstraintSet,分別是restlikepass。如今咱們須要讓一個狀態以點擊或者滑動的方式過渡debug

咱們加入了<OnSwipe>

<Transition
        app:constraintSetEnd="@+id/pass"
        app:constraintSetStart="@+id/rest"
        app:duration="300" >
        <OnSwipe
            app:dragDirection="dragLeft"
            app:onTouchUp="autoComplete"
            app:touchAnchorId="@id/topCard"
            app:touchAnchorSide="left"
            app:touchRegionId="@id/topCard" />
    </Transition>
複製代碼

like部分是鏡像的

如今咱們能夠這樣

使卡片自動飛出屏幕

爲了使卡片飛出屏幕,咱們還須要添加兩個ConstraintSet:offscreenLikeoffscreenPass

<ConstraintSet android:id="@+id/offscreenLike"
        app:deriveConstraintsFrom="@id/like">
        <Constraint
            android:id="@id/topCard"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_marginBottom="80dp"
            android:layout_marginEnd="50dp"
            android:layout_marginTop="20dp"
            app:layout_constraintStart_toEndOf="parent"
            app:layout_constraintWidth_percent="0.7" />
    </ConstraintSet>
複製代碼

咱們想何時卡片飛出屏幕呢?當卡片處於like階段或者pass的時候。

所以,咱們加入Transition

<Transition
        app:autoTransition="animateToEnd"
        app:constraintSetEnd="@+id/offscreenLike"
        app:constraintSetStart="@+id/like"
        app:duration="150" />
複製代碼

底部卡片

咱們如今須要在layout中添加咱們的底部卡片。

<FrameLayout
            android:id="@+id/topCard"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:background="@color/cardview_shadow_start_color">
        </FrameLayout>
複製代碼

res/xml的MotionScene中,咱們須要更改每一個ConstraintSet

<ConstraintSet android:id="@id/rest">
    <!-- ... -->
    <Constraint android:id="@id/bottomCard">
        <Layout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_marginBottom="50dp"
            android:layout_marginEnd="50dp"
            android:layout_marginStart="50dp"
            android:layout_marginTop="50dp" />
        <Transform
            android:scaleX="0.90"
            android:scaleY="0.90" />
    </Constraint>
</ConstraintSet>
<ConstraintSet
    android:id="@+id/offScreenLike"
    app:deriveConstraintsFrom="@id/like">
    <!-- ... -->
    <Constraint android:id="@id/bottomCard">
        <Transform
            android:scaleX="1"
            android:scaleY="1" />
    </Constraint>
</ConstraintSet>
複製代碼

使卡片能夠無限多

咱們須要手動添加代碼來讓卡片滑動到offscreenLike階段的時候,重置回rest階段

private fun setInfinite() {
        motionLayout.setTransitionListener(object : TransitionAdapter() {
            override fun onTransitionCompleted(motionLayout: MotionLayout?, currentId: Int) {
                when (currentId) {

                    R.id.offscreenLike, R.id.offscreenPass -> {
                        motionLayout?.progress = 0f
                        motionLayout?.setTransition(R.id.rest, R.id.like)
                    }
                }
            }
        })
    }
複製代碼

添加額外的View

咱們最後再在xml中添加兩個View

<ImageView
            android:id="@+id/likeIcon"
            android:src="@drawable/ic_baseline_favorite_border"
            android:tint="#fbc02d"
            android:background="@drawable/backround_circle"
            android:layout_height="0dp"
            android:layout_width="0dp" />
複製代碼

,而後更改MotionScene中相應的ConstraintSet,

<ConstraintSet android:id="@+id/like"
        app:deriveConstraintsFrom="@id/rest">
		..........

        <Constraint android:id="@+id/likeIcon">

            <Layout
                android:layout_width="100dp"
                android:layout_height="100dp"
                app:layout_constraintBottom_toBottomOf="@id/topCard"
                app:layout_constraintEnd_toEndOf="@id/topCard"
                app:layout_constraintStart_toStartOf="@id/topCard"
                app:layout_constraintTop_toTopOf="@id/topCard" />

            <Transform
                android:scaleX="1"
                android:scaleY="1" />

            <PropertySet android:alpha="1" />

        </Constraint>
複製代碼

以及

<ConstraintSet android:id="@+id/rest">
        .....................

        <Constraint android:id="@+id/likeIcon">

            <Layout
                android:layout_width="40dp"
                android:layout_height="40dp"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintStart_toEndOf="parent"
                app:layout_constraintTop_toTopOf="parent" />

            <Transform
                android:scaleX="0.5"
                android:scaleY="0.5" />

            <PropertySet android:alpha="0" />


        </Constraint>
複製代碼

這樣,就實現了咱們想要的效果

最後附上github項目地址,其中用到了這個動畫

參考:Medium

相關文章
相關標籤/搜索