Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Changing the alpha in a keyframe in a MotionLayout

I have a motion scene which transitions some views to new locations and changes some alpha values. The MotionScene is basically linear as of now, meaning it has a start state and an end state.

However i would like to have two views to be at alpha 0 earlier than the rest of the views. Say at 10% of the transition the title and subtitle should be faded out completely. To my understanding this can be done with KeyFrameSet. I have done some work on the MotionScene but i dont see any changes in behaviour. Any help would be greatly appreciated!

Here's my MotionScene

<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">


    <Transition
        app:constraintSetEnd="@+id/end"
        app:constraintSetStart="@+id/start"
        app:duration="300">
        <OnSwipe
            app:dragDirection="dragDown"
            app:touchAnchorId="@+id/thumbnail" />


        <KeyFrameSet>
            <KeyAttribute
                android:alpha="1"
                app:motionProgress="0"
                app:motionTarget="@+id/title" />

            <KeyAttribute
                android:alpha="0"
                app:motionProgress="10"
                app:motionTarget="@+id/title" />

        </KeyFrameSet>

    </Transition>


    <ConstraintSet android:id="@+id/start">

        <Constraint
            android:id="@+id/background_card"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent">
            <CustomAttribute
                app:attributeName="cornerRadiusDp"
                app:customFloatValue="0.0" />

        </Constraint>
    </ConstraintSet>

    <ConstraintSet android:id="@+id/end">

        <Constraint
            android:id="@+id/background_card"
            android:layout_width="60dp"
            android:layout_height="60dp"
            android:layout_marginRight="16dp"
            android:layout_marginBottom="16dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintRight_toRightOf="parent">
            <CustomAttribute
                app:attributeName="cornerRadiusDp"
                app:customFloatValue="16.0" />

        </Constraint>

        <Constraint
            android:id="@+id/thumbnail"
            android:layout_width="40dp"
            android:layout_height="40dp"
            app:layout_constraintBottom_toBottomOf="@+id/background_card"
            app:layout_constraintLeft_toLeftOf="@+id/background_card"
            app:layout_constraintRight_toRightOf="@+id/background_card"
            app:layout_constraintTop_toTopOf="@+id/background_card" />
        <Constraint
            android:id="@+id/background"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:alpha="0" />
        <Constraint
            android:id="@+id/toolbar"
            android:layout_width="0dp"
            android:layout_height="56dp"
            android:alpha="0"
            app:layout_constraintLeft_toLeftOf="@+id/background_card"
            app:layout_constraintRight_toRightOf="@+id/background_card"
            app:layout_constraintTop_toTopOf="@+id/background_card" />

        <Constraint
            android:id="@+id/controls_container"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:alpha="0"
            app:layout_constraintBottom_toBottomOf="@+id/background_card"
            app:layout_constraintLeft_toLeftOf="@+id/background_card"
            app:layout_constraintRight_toRightOf="@+id/background_card" />

        <Constraint
            android:id="@+id/title"
            app:layout_constraintBottom_toTopOf="@+id/subtitle"
            app:layout_constraintLeft_toLeftOf="@+id/background_card"
            app:layout_constraintRight_toRightOf="@+id/background_card" />

        <Constraint
            android:id="@+id/subtitle"
            app:layout_constraintBottom_toTopOf="@+id/controls_container"
            app:layout_constraintLeft_toLeftOf="@+id/background_card"
            app:layout_constraintRight_toRightOf="@+id/background_card" />


    </ConstraintSet>


</MotionScene>
like image 293
sn0ep Avatar asked Jan 15 '20 08:01

sn0ep


2 Answers

I have not yet played with KeyFrames and they may work for this but I have messed around with motionStagger a bit and it can definitely work for this. Though the math is a little tricky, it's easy to go through a trial and error to find the intervals you want.

In this stack overflow post I asked about motionStagger and ended up attempting to explain the math, but still it's a little tricky for me. Take a look at the post though if you want to dig in on it.

I would recommend setting a pretty moderate staggerValue to start and messing around with it more as you figure out which part does what. If you just have two different sets of views that you want to stagger, it doesn't matter what you set your motionStagger to, just know that the views with the higher value will animate in first. The value you may want to play around with more is motion:staggered on the Transition element

Try this code and see if it does what you'd like:

<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">


<Transition
    app:constraintSetEnd="@+id/end"
    app:constraintSetStart="@+id/start"
    app:duration="300"
    motion:staggered="0.6>  <--- mess around with this value
    <OnSwipe
        app:dragDirection="dragDown"
        app:touchAnchorId="@+id/thumbnail" />
</Transition>

<ConstraintSet android:id="@+id/start">
    <Constraint
        android:id="@+id/background_card"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent">
        <CustomAttribute
            app:attributeName="cornerRadiusDp"
            app:customFloatValue="0.0" />
        <Motion motion:motionStagger="1" />
    </Constraint>
    <Constraint
        android:id="@+id/title"
        app:layout_constraintBottom_toTopOf="@+id/subtitle"
        app:layout_constraintLeft_toLeftOf="@+id/background_card"
        app:layout_constraintRight_toRightOf="@+id/background_card" >
        <CustomAttribute
            motion:attributeName="alpha"
            motion:customFloatValue="1.0" />
        <Motion motion:motionStagger="2" />
    </Constraint>

    <Constraint
        android:id="@+id/subtitle"
        app:layout_constraintBottom_toTopOf="@+id/controls_container"
        app:layout_constraintLeft_toLeftOf="@+id/background_card"
        app:layout_constraintRight_toRightOf="@+id/background_card" >
        <CustomAttribute
            motion:attributeName="alpha"
            motion:customFloatValue="1.0" />
        <Motion motion:motionStagger="2" />
    </Constraint>
</ConstraintSet>

<ConstraintSet android:id="@+id/end">
    <Constraint
        android:id="@+id/background_card"
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:layout_marginRight="16dp"
        android:layout_marginBottom="16dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintRight_toRightOf="parent">
        <CustomAttribute
            app:attributeName="cornerRadiusDp"
            app:customFloatValue="16.0" />
    </Constraint>

    <Constraint
        android:id="@+id/thumbnail"
        android:layout_width="40dp"
        android:layout_height="40dp"
        app:layout_constraintBottom_toBottomOf="@+id/background_card"
        app:layout_constraintLeft_toLeftOf="@+id/background_card"
        app:layout_constraintRight_toRightOf="@+id/background_card"
        app:layout_constraintTop_toTopOf="@+id/background_card" />

    <Constraint
        android:id="@+id/background"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:alpha="0" />

    <Constraint
        android:id="@+id/toolbar"
        android:layout_width="0dp"
        android:layout_height="56dp"
        android:alpha="0"
        app:layout_constraintLeft_toLeftOf="@+id/background_card"
        app:layout_constraintRight_toRightOf="@+id/background_card"
        app:layout_constraintTop_toTopOf="@+id/background_card" />

    <Constraint
        android:id="@+id/controls_container"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:alpha="0"
        app:layout_constraintBottom_toBottomOf="@+id/background_card"
        app:layout_constraintLeft_toLeftOf="@+id/background_card"
        app:layout_constraintRight_toRightOf="@+id/background_card" />

    <Constraint
        android:id="@+id/title"
        app:layout_constraintBottom_toTopOf="@+id/subtitle"
        app:layout_constraintLeft_toLeftOf="@+id/background_card"
        app:layout_constraintRight_toRightOf="@+id/background_card" >
        <CustomAttribute
            motion:attributeName="alpha"
            motion:customFloatValue="0.0" />
        <Motion motion:motionStagger="2" />
    </Constraint>

    <Constraint
        android:id="@+id/subtitle"
        app:layout_constraintBottom_toTopOf="@+id/controls_container"
        app:layout_constraintLeft_toLeftOf="@+id/background_card"
        app:layout_constraintRight_toRightOf="@+id/background_card" >
        <CustomAttribute
            motion:attributeName="alpha"
            motion:customFloatValue="0.0" />
        <Motion motion:motionStagger="2" />
    </Constraint>
</ConstraintSet>

Hope that works for you! I marked the line above in the code that will mess with the stagger

like image 51
kjanderson2 Avatar answered Oct 16 '22 14:10

kjanderson2


In order to make alpha = 0 earlier, KeyFrameSet should look like this:

   <KeyFrameSet>
       <KeyAttribute
           motion:framePosition="0"
           motion:motionTarget="@id/view">
           <CustomAttribute
               motion:attributeName="alpha"
               motion:customFloatValue="1" />
       </KeyAttribute>

       <KeyAttribute
           motion:framePosition="50"
           motion:motionTarget="@id/view">
           <CustomAttribute
               motion:attributeName="alpha"
               motion:customFloatValue="0" />
       </KeyAttribute>
   </KeyFrameSet>

In this case "view" will become invisible at center of animation (because of 50)

like image 1
Andrey Kijonok Avatar answered Oct 16 '22 13:10

Andrey Kijonok