I'm using MotionLayout and <MotionScene /> to animate a bottomSheet View content, following swipe animation.
Between start and end scenes I'd like to make appear a view view_player_status_margin using visibility from gone to visible (not using alpha because an other view is link by constraint to the one I want to make appears).
It's ok using standard <Constraint /> in <ConstraintSet />, but when I link visibility to a <KeyAttribute /> to make the view appears only on last frames of the animation it doesn't doesn't follow the frame specific rule position.
My usage of <KeyAttribute /> seems correct because it works on alpha for the two others views.
Is there specific restrictions using KeyAttribute with visibilityattribute ?
<?xml version="1.0" encoding="utf-8"?>
<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<Transition
app:constraintSetEnd="#+id/player_scene_set_expanded"
app:constraintSetStart="#+id/player_scene_set_collapsed"
app:motionInterpolator="easeIn">
<KeyFrameSet>
<KeyAttribute
android:visibility="gone"
app:framePosition="80"
app:motionTarget="#id/view_player_status_margin" />
<KeyAttribute
android:alpha="0"
app:framePosition="20"
app:motionTarget="#id/view_player_collapsed" />
<KeyAttribute
android:alpha="1"
app:framePosition="20"
app:motionTarget="#id/view_player_expanded" />
</KeyFrameSet>
</Transition>
<ConstraintSet android:id="#+id/player_scene_set_collapsed">
<Constraint
android:id="#+id/view_player_collapsed"
android:layout_width="0dp"
android:layout_height="64dp"
android:alpha="1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<Constraint
android:id="#+id/view_player_expanded"
android:layout_width="0dp"
android:layout_height="0dp"
android:alpha="0"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/view_player_status_margin"/>
<Constraint
android:id="#+id/view_player_status_margin"
android:layout_width="0dp"
android:layout_height="38dp"
android:visibility="gone"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</ConstraintSet>
<ConstraintSet android:id="#+id/player_scene_set_expanded">
<Constraint
android:id="#+id/view_player_collapsed"
android:layout_width="0dp"
android:layout_height="64dp"
android:alpha="0"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<Constraint
android:id="#+id/view_player_expanded"
android:layout_width="0dp"
android:layout_height="0dp"
android:alpha="1"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/view_player_status_line" />
<Constraint
android:id="#+id/view_player_status_line"
android:layout_width="0dp"
android:layout_height="38dp"
android:visibility="visible"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</ConstraintSet>
</MotionScene>
I wanted to do something like this, and as a beginner it's a bit confusing to me, but I thought to share what I could do so far.
For me, I couldn't find an KeyAttribute for visibility, so I had to make use of CustomAttribute:
<KeyAttribute
motion:framePosition="0"
motion:motionTarget="#id/background">
<CustomAttribute
motion:attributeName="visibility"
motion:customIntegerValue="8" />
</KeyAttribute>
And following are the corresponding integer values for visibility are:
Visible = 0
Invisible = 4
Gone = 8
So, for my need, I had a background view, and I wanted motion to animate its alpha from 0 to 1. The background view should be gone when alpha is 0, and once alpha is getting greater than 0 just stay visible all the time, but I don't want any animation for visibility at all.
Configuring a KeyFrameSet was not enough for me, I had to tell motion to ignore animating visibility of the background view.
Of course, I had to set visibility of the background view for #id/start and #id/end constraint sets, following is the MotionScene demonstrating all of this:
<MotionScene
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:motion="http://schemas.android.com/apk/res-auto">
<Transition
android:id="#+id/transition"
motion:constraintSetEnd="#+id/end"
motion:constraintSetStart="#id/start"
motion:duration="#integer/standard_duration">
<KeyFrameSet>
<KeyAttribute
motion:framePosition="0"
motion:motionTarget="#id/background">
<CustomAttribute
motion:attributeName="visibility"
motion:customIntegerValue="8" />
</KeyAttribute>
<KeyAttribute
motion:framePosition="1"
motion:motionTarget="#id/background">
<CustomAttribute
motion:attributeName="visibility"
motion:customIntegerValue="0" />
</KeyAttribute>
</KeyFrameSet>
</Transition>
<ConstraintSet android:id="#+id/start">
...
<Constraint
android:id="#+id/background"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:alpha="0.5"
android:visibility="gone"
motion:visibilityMode="ignore"
/>
</ConstraintSet>
<ConstraintSet android:id="#+id/end">
...
<Constraint
android:id="#+id/background"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:alpha="0.5"
android:visibility="visible"
motion:visibilityMode="ignore"
/>
</ConstraintSet>
</MotionScene>
Related
IN androids motionLayout i need to change the color while the view transitions. but it seems to not take resource links such as "#drawable/myshape". it wants raw values like "#FFFFFF". here is what i have done so far:
<?xml version="1.0" encoding="utf-8"?>
<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<Transition
android:id="#+id/transition"
app:constraintSetEnd="#id/end"
app:constraintSetStart="#id/start"
app:motionInterpolator="linear"
app:moveWhenScrollAtTop="true">
</Transition>
<ConstraintSet android:id="#+id/start">
<Constraint
android:id="#+id/spaceShip"
android:layout_width="0dp"
android:layout_height="0dp"
android:alpha="1"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" >
<!-- <CustomAttribute-->
<!-- app:attributeName="backgroundColor"-->
<!-- app:customColorValue="#drawable/space_spaceShip_bg" />-->
//the above code does not work. it wants a raw value, how to specify it from a drawable as i created a custom background shape already for my background.
</Constraint>
</ConstraintSet>
<ConstraintSet android:id="#+id/end">
<Constraint
android:id="#+id/spaceShip"
android:layout_width="0dp"
android:layout_height="0dp"
android:alpha="0"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" >
<CustomAttribute
app:attributeName="backgroundColor"
app:customColorValue="#FFFFFF" /> //also here how to specify #color/white instead of raw value
</Constraint>
</ConstraintSet>
</MotionScene>
it seems the way to do this is to find a property of some view that has a setter that scales from 0 to 1. the [imageFilterView][1] class is one such.
it has a property called [setcrossfade][2]
so my motionlayout can look like this:
<?xml version="1.0" encoding="utf-8"?>
<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<Transition
android:id="#+id/transition"
app:constraintSetEnd="#id/end"
app:constraintSetStart="#id/start">
</Transition>
<ConstraintSet android:id="#+id/start">
<Constraint
android:id="#+id/myview"
android:layout_width="0dp"
android:layout_height="0dp"
android:alpha="1"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" >
<CustomAttribute
app:attributeName="crossfade"
app:customFloatValue="0" />
</Constraint>
</ConstraintSet>
<ConstraintSet android:id="#+id/end">
<Constraint
android:id="#+id/myview"
android:layout_width="0dp"
android:layout_height="0dp"
android:alpha="0"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" >
<CustomAttribute
app:attributeName="crossfade"
app:customFloatValue="1" />
</Constraint>
</ConstraintSet>
</MotionScene>
and in our layout file we can do this:
<androidx.constraintlayout.motion.widget.MotionLayout
android:id="#+id/ml"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_gravity="bottom"
app:layoutDescription="#xml/motion_scene">
<androidx.constraintlayout.utils.widget.ImageFilterView
android:id="#+id/myview"
android:layout_width="0dp"
android:layout_height="0dp"
android:src="#drawable/bg1"
app:altSrc="#drawable/bg2"
android:background="#drawable/bg1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
/>
</androidx.constraintlayout.motion.widget.MotionLayout>
transition it how you want ..manually or using a swipe in the motion layout file. anyway afterwards, it will fade out one drawable and fade in another one. exactly what i wanted.
[1]: https://developer.android.com/reference/androidx/constraintlayout/utils/widget/ImageFilterView
[2]: https://developer.android.com/reference/androidx/constraintlayout/utils/widget/ImageFilterView#setCrossfade(float)
I currently going my first steps into motion layout.
The example I want to create is the following:
A motion layout with two FABs in it (a mini and a normal one). The image above shows the end state after clicking the normal sized FAB.
What I've tried:
Motion Layout (is part of an other layout file):
<androidx.constraintlayout.motion.widget.MotionLayout
android:id="#+id/include"
app:motionDebug="SHOW_PATH"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#android:color/darker_gray"
android:layout_margin="8dp"
app:layoutDescription="#xml/menu_scene"
app:layout_constraintTop_toBottomOf="#id/text"
app:layout_constraintStart_toStartOf="#id/text"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent">
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="#+id/images_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="#id/menu_button"
app:layout_constraintTop_toTopOf="#id/menu_button"
app:layout_constraintBottom_toBottomOf="#id/menu_button"
android:src="#drawable/ic_image"
app:fabSize="mini" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="#+id/menu_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:src="#drawable/ic_edit" />
</androidx.constraintlayout.motion.widget.MotionLayout>
MotionScene:
<MotionScene xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">
<Transition
app:constraintSetStart="#+id/start"
app:constraintSetEnd="#+id/end">
<OnClick
app:targetId="#+id/menu_button"
app:clickAction="toggle" />
</Transition>
<!-- pulls constraints from layout -->
<ConstraintSet android:id="#+id/start" />
<ConstraintSet android:id="#+id/end">
<Constraint android:id="#id/images_button">
<Layout
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
</Constraint>
</ConstraintSet>
</MotionScene>
But unfortunately with this configuration I got this:
The tiny pink dot on the bottom left is the mini FAB.
Because I heard about deriveConstraintsFrom I gave it a chance:
<MotionScene ...>
<Transition ...>
...
</Transition>
<ConstraintSet android:id="#+id/start" />
<ConstraintSet
android:id="#+id/end"
app:deriveConstraintsFrom="#id/start">
<Constraint android:id="#id/images_button">
...
</Constraint>
</ConstraintSet>
</MotionScene>
But I got the same result! :(
The only way I got the wanted result was with the following constraint set configuration:
<MotionScene ...>
...
<ConstraintSet android:id="#+id/start" />
<ConstraintSet android:id="#+id/end">
<Constraint android:id="#id/images_button">
<!-- duplicated the layout properties from the initial layout :( -->
<Layout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="#id/menu_button"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
</Constraint>
</ConstraintSet>
</MotionScene>
Wrap up:
I thought the empty constraint set <ConstraintSet android:id="#+id/start" /> pulls the its contrains from the layout itself and app:deriveConstraintsFrom="#id/start" on the other constraint set specifies all constraints from the initial constraint set and overwrites its own.
Can somebody tell me why this isn't working? Or did I miss something?
Thanks, Chris
PS.: I using androidx.constraintlayout:constraintlayout:2.0.0-beta4
Is it possible to implement draggable panel!
using motion layout?
I have tried to play around the google sample of youtube like transition by using multiple Transitions with OnSwipe on a single view but not able to succeed. Can anyone please guide me to implement how to apply the two transitions using OnSwipe on the same view?
<?xml version="1.0" encoding="utf-8"?>
<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<Transition
app:constraintSetEnd="#id/expanded"
app:constraintSetStart="#id/collapsed"
app:duration="100"
app:interpolator="easeInOut">
<OnSwipe
app:dragDirection="dragUp"
app:maxAcceleration="200"
app:touchAnchorId="#+id/videoViewContainer"
app:touchAnchorSide="top" />
<KeyFrameSet>
<!--<KeyAttribute-->
<!--app:framePosition="0"-->
<!--app:target="#id/videoView">-->
<!--<CustomAttribute-->
<!--app:attributeName="EndPadding"-->
<!--app:customDimension="#dimen/video_view_right_padding" />-->
<!--</KeyAttribute>-->
<!--<KeyAttribute-->
<!--app:framePosition="20"-->
<!--app:target="#id/videoView">-->
<!--<CustomAttribute-->
<!--app:attributeName="EndPadding"-->
<!--app:customDimension="0dp" />-->
<!--</KeyAttribute>-->
<KeyAttribute
app:framePosition="0"
app:target="#id/videoMotionLayout">
<CustomAttribute
app:attributeName="height"
app:customDimension="90dp" />
</KeyAttribute>
<KeyAttribute
app:framePosition="20"
app:target="#id/videoMotionLayout">
<CustomAttribute
app:attributeName="height"
app:customDimension="250dp" />
</KeyAttribute>
<KeyAttribute
app:framePosition="0"
app:target="#id/videoMotionLayout">
<CustomAttribute
app:attributeName="width"
app:customDimension="160dp" />
</KeyAttribute>
<KeyAttribute
app:framePosition="20"
app:target="#id/videoMotionLayout">
<CustomAttribute
app:attributeName="width"
app:customDimension="0dp" />
</KeyAttribute>
<KeyAttribute
android:alpha="0"
app:framePosition="0"
app:target="#id/videoRecyclerView" />
<KeyAttribute
android:alpha="1"
app:framePosition="100"
app:target="#id/videoRecyclerView" />
<KeyAttribute
app:framePosition="0"
app:target="#id/videoViewContainer">
<CustomAttribute
app:attributeName="cardElevation"
app:customDimension="5dp" />
</KeyAttribute>
<KeyAttribute
app:framePosition="3"
app:target="#id/videoViewContainer">
<CustomAttribute
app:attributeName="cardElevation"
app:customDimension="0dp" />
</KeyAttribute>
</KeyFrameSet>
</Transition>
<Transition
app:constraintSetEnd="#id/close"
app:constraintSetStart="#id/close"
app:duration="100"
app:interpolator="easeInOut">
<OnSwipe
app:dragDirection="dragLeft"
app:maxAcceleration="200"
app:touchAnchorId="#+id/videoViewContainer"
app:touchAnchorSide="top" />
<KeyFrameSet>
<KeyAttribute
app:framePosition="0"
app:target="#id/videoMotionLayout">
</KeyAttribute>
</KeyFrameSet>
</Transition>
<Transition
app:constraintSetEnd="#id/close"
app:constraintSetStart="#id/close"
app:duration="100"
app:interpolator="easeInOut">
<OnSwipe
app:dragDirection="dragRight"
app:maxAcceleration="200"
app:touchAnchorId="#+id/videoViewContainer"
app:touchAnchorSide="top" />
<KeyFrameSet>
</KeyFrameSet>
</Transition>
<ConstraintSet android:id="#+id/close">
<Constraint
android:id="#id/videoViewContainer"
android:layout_height="250dp"
android:layout_marginStart="0dp"
android:layout_marginEnd="0dp"
android:layout_marginBottom="0dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Constraint
android:id="#id/content"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginStart="0dp"
android:layout_marginEnd="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/videoViewContainer" />
</ConstraintSet>
<ConstraintSet android:id="#+id/collapsed">
<Constraint
android:id="#id/videoViewContainer"
android:layout_height="113dp"
android:layout_width="200dp"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:layout_marginBottom="65dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
<Constraint
android:id="#id/content"
android:layout_width="match_parent"
android:layout_height="-1dp"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:layout_marginBottom="66dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/videoViewContainer" />
</ConstraintSet>
</MotionScene>
It would be helpful If I can move the mini-player scene to the left and right directions as well. Thank you.
How to create multiple transitions on a single view
It is possible to add multiple transitions to the same View. For example we can define animations with motion:dragDirection="dragDown" and motion:dragDirection="dragUp" on the same touchAnchorId without any problem. The possible configurations are given below,
motion:dragDirection="dragUp"
motion:dragDirection="dragDown"
motion:dragDirection="dragLeft"
motion:dragDirection="dragRight"
What to do
So, here I show you how to implement all these together on the same View.
Before writing any code, please see the below gif to better understand what we are trying to create.
How to do
Add the ConstraintLayout dependency:
dependencies {
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta2'
}
Create a MotionLayout file:
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.motion.widget.MotionLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:motion="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/motionLayout"
motion:layoutDescription="#xml/motionscene1"
android:layout_width="match_parent"
android:layout_height="match_parent">
<View
android:id="#+id/image"
android:layout_width="match_parent"
android:layout_height="240dp"
android:background="#453672"
motion:layout_constraintStart_toStartOf="parent"
motion:layout_constraintTop_toTopOf="parent"/>
</androidx.constraintlayout.motion.widget.MotionLayout>
Create a MotionScene:
A MotionScene is an XML resource file that contains all of the motion descriptions for the corresponding layout. Put the file under res/xml/ folder
motionscene1.xml
<?xml version="1.0" encoding="utf-8"?>
<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:motion="http://schemas.android.com/apk/res-auto">
<!-- top to bottom right-->
<Transition
motion:constraintSetEnd="#id/step2"
motion:constraintSetStart="#id/step1"
motion:duration="500">
<OnSwipe
motion:dragDirection="dragDown"
motion:touchAnchorId="#id/image"
motion:touchAnchorSide="top" />
</Transition>
<!-- bottom right to bottom left-->
<Transition
motion:constraintSetEnd="#id/step3"
motion:constraintSetStart="#id/step2"
motion:duration="500">
<OnSwipe
motion:dragDirection="dragLeft"
motion:touchAnchorId="#id/image"
motion:touchAnchorSide="left" />
</Transition>
<!-- bottom left to top-->
<Transition
motion:constraintSetEnd="#id/step1"
motion:constraintSetStart="#id/step3"
motion:duration="500">
<OnSwipe
motion:dragDirection="dragUp"
motion:touchAnchorId="#id/image"
motion:touchAnchorSide="top" />
</Transition>
<!-- bottom right to top-->
<Transition
motion:constraintSetEnd="#id/step1"
motion:constraintSetStart="#id/step2"
motion:duration="500">
<OnSwipe
motion:dragDirection="dragUp"
motion:touchAnchorId="#id/image"
motion:touchAnchorSide="top" />
</Transition>
<!-- place the view on top-->
<ConstraintSet android:id="#+id/step1">
<Constraint
android:id="#id/image"
android:layout_width="match_parent"
android:layout_height="240dp"
android:layout_marginStart="0dp"
android:layout_marginLeft="0dp"
android:layout_marginTop="0dp"
android:layout_marginEnd="0dp"
android:layout_marginRight="0dp"
android:layout_marginBottom="0dp"
motion:layout_constraintStart_toStartOf="parent"
motion:layout_constraintTop_toTopOf="parent">
<PropertySet android:alpha="1" />
</Constraint>
</ConstraintSet>
<!-- place the view on bottom right-->
<ConstraintSet android:id="#+id/step2">
<Constraint
android:id="#id/image"
android:layout_width="150dp"
android:layout_height="100dp"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:layout_marginBottom="16dp"
motion:layout_constraintBottom_toBottomOf="parent"
motion:layout_constraintEnd_toEndOf="parent">
<PropertySet android:alpha="1" />
</Constraint>
</ConstraintSet>
<!-- place the view on bottom left-->
<ConstraintSet android:id="#+id/step3">
<Constraint
android:id="#id/image"
android:layout_width="150dp"
android:layout_height="100dp"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:layout_marginBottom="16dp"
motion:layout_constraintBottom_toBottomOf="parent"
motion:layout_constraintStart_toStartOf="parent">
<PropertySet android:alpha="1" />
</Constraint>
</ConstraintSet>
</MotionScene>
That's all. You created an amazing custom animation with out writing any java/kotlin code. MotionLayout is fully declarative, meaning that you can describe any transitions in XML, no matter how complex.
I'm trying to make an effect of fade in, fade out using alpha and motionLayout, but it seems that it's not working.
This is the imageView that I want to fade.
<ImageView
android:id="#+id/tijeras"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="8dp"
android:contentDescription="#string/tijeras"
android:src="#drawable/ic_tijeras" />
</android.support.constraint.motion.MotionLayout>
And this is the motion file
<?xml version="1.0" encoding="utf-8"?>
<MotionScene xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">
<Transition
app:duration="2000"
app:constraintSetStart="#+id/start"
app:constraintSetEnd="#+id/end">
<KeyFrameSet>
<KeyAttribute
app:framePosition="0"
app:motionTarget="#id/tijeras"
android:alpha="1.0"/>
<KeyAttribute
app:framePosition="50"
app:motionTarget="#id/tijeras"
android:alpha="0.0"/>
</KeyFrameSet>
</Transition>
<ConstraintSet android:id="#+id/start">
<Constraint android:id="#+id/tijeras"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:alpha="1.0"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/logo"/>
</ConstraintSet>
<ConstraintSet android:id="#+id/end">
<Constraint android:id="#+id/tijeras"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:alpha="1.0"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/logo"/>
</ConstraintSet>
</MotionScene>
I can see the image, but it's not doing the alpha in and out. Any idea? Do I need to trigger it for starting?
It looks like you have set the alpha as 1.0 android:alpha="1.0" on both the start and end ConstraintSet.
You can more easily set the alpha to update with a CustomAttribute by removing alpha from the KeyAttribute and placing the following below your Transition element
<ConstraintSet android:id="#+id/start">
<Constraint android:id="#+id/tijeras"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/logo">
<CustomAttribute
motion:attributeName="alpha"
motion:customFloatValue="0.0" />
</Constraint>
</ConstraintSet>
<ConstraintSet android:id="#+id/end">
<Constraint android:id="#+id/tijeras"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:alpha="1.0"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/logo">
<CustomAttribute
motion:attributeName="alpha"
motion:customFloatValue="1.0" />
</Constraint>
</ConstraintSet>
I think that i have found the problem and the solution. So you are defining two ConstraintSet (start, end) and in both alpha = 1, it means that your view is visible in both of them right ? Now let's see your KeyFrameSet
<KeyFrameSet>
<KeyAttribute
app:framePosition="0"
app:motionTarget="#id/tijeras"
android:alpha="1.0"/>
<KeyAttribute
app:framePosition="50"
app:motionTarget="#id/tijeras"
android:alpha="0.0"/>
</KeyFrameSet>
You're saying that at framePosition = 0 your view is visible (alpha=1), then in the middle of your transition (framePosition = 50 ) you are hiding your view (alpha=0). It means that when you are at framePosition = 100 (end of your transition) the alpha will be 1 again because in your ConstraintSet (end) is equal to 1.
So try to change it like this, instead of 50, framePosition = 100
<KeyFrameSet>
<KeyAttribute
app:framePosition="0"
app:motionTarget="#id/tijeras"
android:alpha="1.0"/>
<KeyAttribute
app:framePosition="100"
app:motionTarget="#id/tijeras"
android:alpha="0.0"/>
</KeyFrameSet>
There is no need setting a CustomAttribute, this solution should work:
BaseView
<!-- Other views -->
<ImageView
android:id="#+id/tijeras"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="8dp"
android:contentDescription="#string/tijeras"
android:src="#drawable/ic_tijeras" />
Content Scene
<MotionScene xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">
<Transition
app:duration="2000"
app:constraintSetStart="#+id/start"
app:constraintSetEnd="#+id/end">
<KeyFrameSet>
<KeyAttribute
app:framePosition="50"
app:motionTarget="#id/tijeras"
android:alpha="0.0"/> <!-- Set alpha to zero -->
</KeyFrameSet>
</Transition>
<ConstraintSet android:id="#+id/start">
<ConstraintSet android:id="#+id/end">
<Constraint android:id="#id/tijeras" <!-- without + -->
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:alpha="0.0" <!-- set alpha to zero -->
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/logo"/>
</ConstraintSet>
</MotionScene>
I am getting
"Failed linking file resources"
with
"error: attribute type (aka com.testapp.client:type) not found"
When using the new MotionLayout, specifically when adding a KeyPosition element to the scene file.
My scene file for reference:
<?xml version="1.0" encoding="utf-8"?>
<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<Transition
app:constraintSetEnd="#id/collapsed"
app:constraintSetStart="#id/expanded">
<OnSwipe
app:dragDirection="dragUp"
app:touchAnchorId="#id/recyclerview"
app:touchAnchorSide="top" />
<KeyFrameSet>
<KeyAttribute
app:framePosition="60"
app:target="#id/toolbar_image">
<CustomAttribute
app:attributeName="imageAlpha"
app:customIntegerValue="255" />
</KeyAttribute>
<KeyAttribute
app:framePosition="90"
app:target="#id/toolbar_image">
<CustomAttribute
app:attributeName="imageAlpha"
app:customIntegerValue="0" />
</KeyAttribute>
<KeyPosition
app:type="pathRelative"
app:framePosition="50"
app:target="#id/title"
app:percentX="0.9" />
</KeyFrameSet>
</Transition>
<ConstraintSet android:id="#+id/expanded">
<Constraint
android:id="#id/toolbar_image"
android:layout_height="200dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Constraint
android:id="#id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginBottom="24dp"
android:scaleX="1.0"
android:scaleY="1.0"
app:layout_constraintBottom_toBottomOf="#id/toolbar_image"
app:layout_constraintStart_toStartOf="parent" />
</ConstraintSet>
<ConstraintSet android:id="#+id/collapsed">
<Constraint
android:id="#id/toolbar_image"
android:layout_height="?attr/actionBarSize"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Constraint
android:id="#id/title"
android:layout_marginStart="20dp"
android:layout_marginBottom="0dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleX="0.625"
android:scaleY="0.625"
app:layout_constraintBottom_toBottomOf="#id/toolbar_image"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="#id/toolbar_image" />
</ConstraintSet>
I am using Android Studio 3.2 stable, and AndroidX varients of the support libs & constraint layout.
Any help is appreciated :)
For your information, target
has been changed to motionTarget
in KeyPosition and KeyAttribute
Nevermind :)
Attribute "type" on KeyPosition element has been changed in Alpha 2 to be "keyPositionType"
here is a snippet if anyone is having the same issues:
<KeyPosition
app:keyPositionType="pathRelative"
app:framePosition="50"
app:target="#id/title"
app:percentX="0.9" />
instead of this:
<KeyPosition
app:type="pathRelative"
app:framePosition="50"
app:target="#id/title"
app:percentX="0.9" />
Update:
As #MichałK mentioned in comments in seems to be that
android:interpolator have changed to motion:motionInterpolator
in a later version
Reference: https://developer.android.com/reference/android/support/constraint/motion/MotionLayout.html#transition
Old Post:
In addition to what #Momen mentioned
In <Transition ...> tag motion:interpolator
have been changed to android:interpolator
( Change of namespace from motion to android )
example:
<Transition ...
android:interpolator="#android:anim/accelerate_interpolator">