MotionLayout
MotionLayout
 애니메이션 설정을 위한 ConstraintLayout 을 상속한 레이아웃
 ConstraintLayout 애니메이션과 달리 사용자의 입력에 따른 상호작용 가능
 XML 을 통해 애니메이션을 별도의 코드 없이 정의 가능
 애니메이션 동작을 위한 MotionScene 파일 필요
 직계 Child View 에만 적용할 수 있는 한계점
 Android Support Library 또는 Android X Library 를 통해 사용 가능
Android Support Library Android X Library
Min SDK 18↑ 14↑
Dependency
implementation 'com.android.support.constraint:constraint-
layout:2.0.0-beta1'
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-
beta1'
Refenece
https://developer.android.com/reference/android/support/constraint/
motion/MotionLayout?hl=en
https://developer.android.com/reference/androidx/constraintlayout/m
otion/widget/MotionLayout?hl=en
MotionScene
 레이아웃의 모션에 대한 정보를 포함한 XML 파일
 res/xml 경로에 저장
 ConstraintSet, Transition 등을 포함
 Alpha, Visibility, Rotation 등의 값을 설정한 애니메이션 가능
 CustomAttribute 를 이용하여 사용자 정의값 추가 가능
 MotionLayout 에 app:layoutDescription 속성에 지정하여 레이아웃과 연결
 MotionScene 에 정의된 내용은 MotionLayout 에 정의된 유사한 내용보다 우선시 됨
Ex01. 기본적인 애니메이션
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.motion.MotionLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutDescription="@xml/ex01_basic_motion"
app:showPaths="true"
tools:context=".ex01basic.Ex01BasicActivity">
<View
android:id="@+id/view"
android:layout_width="60dp"
android:layout_height="60dp"
android:background="@color/colorPrimaryRed"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
</android.support.constraint.motion.MotionLayout>
[ activity_ex01_basic.xml ]
Ex01. 기본적인 애니메이션
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.motion.MotionLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutDescription="@xml/ex01_basic_motion"
app:showPaths="true"
tools:context=".ex01basic.Ex01BasicActivity">
<View
android:id="@+id/view"
android:layout_width="60dp"
android:layout_height="60dp"
android:background="@color/colorPrimaryRed"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
</android.support.constraint.motion.MotionLayout>
[ activity_ex01_basic.xml ]
애니메이션 내용을 기재한 파일 연결
<?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/end"
app:constraintSetStart="@+id/start"
app:duration="1000">
<OnSwipe
app:dragDirection="dragDown"
app:touchAnchorId="@+id/view"
app:touchAnchorSide="bottom" />
</Transition>
<ConstraintSet android:id='@+id/start'>
<Constraint
android:id="@+id/view"
android:layout_width="60dp"
android:layout_height="60dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</ConstraintSet>
<ConstraintSet android:id="@+id/end">
<Constraint
android:id="@+id/view"
android:layout_width="60dp"
android:layout_height="60dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</ConstraintSet>
</MotionScene>
Ex01. 기본적인 애니메이션
[ ex01_basic_motion.xml ]
<?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/end"
app:constraintSetStart="@+id/start"
app:duration="1000">
<OnSwipe
app:dragDirection="dragDown"
app:touchAnchorId="@+id/view"
app:touchAnchorSide="bottom" />
</Transition>
<ConstraintSet android:id='@+id/start'>
<Constraint
android:id="@+id/view"
android:layout_width="60dp"
android:layout_height="60dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</ConstraintSet>
<ConstraintSet android:id="@+id/end">
<Constraint
android:id="@+id/view"
android:layout_width="60dp"
android:layout_height="60dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</ConstraintSet>
</MotionScene>
Ex01. 기본적인 애니메이션
[ ex01_basic_motion.xml ]
애니메이션 시작/끝 상태를 포함한
ConstraintSet 을 명시
<?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/end"
app:constraintSetStart="@+id/start"
app:duration="1000">
<OnSwipe
app:dragDirection="dragDown"
app:touchAnchorId="@+id/view"
app:touchAnchorSide="bottom" />
</Transition>
<ConstraintSet android:id='@+id/start'>
<Constraint
android:id="@+id/view"
android:layout_width="60dp"
android:layout_height="60dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</ConstraintSet>
<ConstraintSet android:id="@+id/end">
<Constraint
android:id="@+id/view"
android:layout_width="60dp"
android:layout_height="60dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</ConstraintSet>
</MotionScene>
Ex01. 기본적인 애니메이션
[ ex01_basic_motion.xml ]
Swipe 시 추적하려는 대상 Id,
추적하려는 모션 방향,
추적하려는 대상의 측면 정의
<?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/end"
app:constraintSetStart="@+id/start"
app:duration="1000">
<OnSwipe
app:dragDirection="dragDown"
app:touchAnchorId="@+id/view"
app:touchAnchorSide="bottom" />
</Transition>
<ConstraintSet android:id='@+id/start'>
<Constraint
android:id="@+id/view"
android:layout_width="60dp"
android:layout_height="60dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</ConstraintSet>
<ConstraintSet android:id="@+id/end">
<Constraint
android:id="@+id/view"
android:layout_width="60dp"
android:layout_height="60dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</ConstraintSet>
</MotionScene>
Ex01. 기본적인 애니메이션
[ ex01_basic_motion.xml ]
애니메이션 시작/끝 상태를 명시
Layout 파일에 기재된 내용보다 우선되어 적용
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.motion.MotionLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutDescription="@xml/ex02_color_change_motion"
app:showPaths="true"
tools:context=".ex02colorchange.Ex02ColorChangeActivity">
<View
android:id="@+id/view"
android:layout_width="60dp"
android:layout_height="60dp"
android:background="@color/colorPrimaryBlack"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
</android.support.constraint.motion.MotionLayout>
Ex02. 색상 변경 애니메이션 (Custom Attribute)
[ activity_ex02_color_change.xml ]
<Transition
app:constraintSetEnd="@+id/end"
app:constraintSetStart="@+id/start"
app:duration="1000">
<OnSwipe
app:dragDirection="dragDown"
app:touchAnchorId="@+id/view"
app:touchAnchorSide="bottom" />
</Transition>
<ConstraintSet android:id='@+id/start'>
<Constraint
android:id="@+id/view"
android:layout_width="60dp"
android:layout_height="60dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<CustomAttribute
app:attributeName="backgroundColor"
app:customColorValue="@color/colorPrimaryBlack" />
</Constraint>
</ConstraintSet>
<ConstraintSet android:id="@+id/end">
<Constraint
android:id="@+id/view"
android:layout_width="60dp"
android:layout_height="60dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<CustomAttribute
app:attributeName="backgroundColor"
app:customColorValue="@color/colorPrimaryRed" />
</Constraint>
</ConstraintSet>
Ex02. 색상 변경 애니메이션 (Custom Attribute)
[ activity_ex02_color_change.xml ]
<Transition
app:constraintSetEnd="@+id/end"
app:constraintSetStart="@+id/start"
app:duration="1000">
<OnSwipe
app:dragDirection="dragDown"
app:touchAnchorId="@+id/view"
app:touchAnchorSide="bottom" />
</Transition>
<ConstraintSet android:id='@+id/start'>
<Constraint
android:id="@+id/view"
android:layout_width="60dp"
android:layout_height="60dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<CustomAttribute
app:attributeName="backgroundColor"
app:customColorValue="@color/colorPrimaryBlack" />
</Constraint>
</ConstraintSet>
<ConstraintSet android:id="@+id/end">
<Constraint
android:id="@+id/view"
android:layout_width="60dp"
android:layout_height="60dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<CustomAttribute
app:attributeName="backgroundColor"
app:customColorValue="@color/colorPrimaryRed" />
</Constraint>
</ConstraintSet>
Ex02. 색상 변경 애니메이션 (Custom Attribute)
[ activity_ex02_color_change.xml ]
변경하려는 속성명과 속성값을 정의
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.motion.MotionLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutDescription="@xml/ex03_image_filter_view_motion"
app:showPaths="true"
tools:context=".Ex03ImageFilterView.Ex03ImageFilterViewActivity">
<android.support.constraint.utils.ImageFilterView
android:id="@+id/imageFilterView"
android:layout_width="120dp"
android:layout_height="120dp"
android:src="@mipmap/ic_launcher"
app:altSrc="@drawable/brown"
android:scaleType="fitCenter"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
</android.support.constraint.motion.MotionLayout>
Ex03. 이미지 교체, 채도 애니메이션 (Custom Attribute)
[ activity_ex03_image_filter_view.xml ]
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.motion.MotionLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutDescription="@xml/ex03_image_filter_view_motion"
app:showPaths="true"
tools:context=".Ex03ImageFilterView.Ex03ImageFilterViewActivity">
<android.support.constraint.utils.ImageFilterView
android:id="@+id/imageFilterView"
android:layout_width="120dp"
android:layout_height="120dp"
android:src="@mipmap/ic_launcher"
app:altSrc="@drawable/brown"
android:scaleType="fitCenter"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
</android.support.constraint.motion.MotionLayout>
Ex03. 이미지 교체, 채도 애니메이션 (Custom Attribute)
[ activity_ex03_image_filter_view.xml ]
android:src 및 app:altSrc 에 애니메이션을 위한 이미지 리소스 명시
ImageFilterView
- AppCompatImageView 를 상속
- 채도, 대비, 온도, 크로스페이드 값을 조절 가능
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.motion.MotionLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutDescription="@xml/ex03_image_filter_view_motion"
app:showPaths="true"
tools:context=".Ex03ImageFilterView.Ex03ImageFilterViewActivity">
<android.support.constraint.utils.ImageFilterView
android:id="@+id/imageFilterView"
android:layout_width="120dp"
android:layout_height="120dp"
android:src="@mipmap/ic_launcher"
app:altSrc="@drawable/brown"
android:scaleType="fitCenter"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
</android.support.constraint.motion.MotionLayout>
Ex03. 이미지 교체, 채도 애니메이션 (Custom Attribute)
android:src 및 app:altSrc 에 애니메이션을 위한 이미지 리소스 명시
ImageFilterView
- AppCompatImageView 를 상속
- 채도, 대비, 온도, 크로스페이드 값을 조절 가능
<MotionScene>
……
<ConstraintSet android:id='@+id/start'>
<Constraint
android:id="@+id/imageFilterView"
android:layout_width="120dp"
android:layout_height="120dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<CustomAttribute
app:attributeName="Crossfade"
app:customFloatValue="0" />
<CustomAttribute
app:attributeName="saturation"
app:customFloatValue="0" />
</Constraint>
</ConstraintSet>
<ConstraintSet android:id="@+id/end">
<Constraint
android:id="@+id/imageFilterView"
android:layout_width="120dp"
android:layout_height="120dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<CustomAttribute
app:attributeName="Crossfade"
app:customFloatValue="1" />
<CustomAttribute
app:attributeName="saturation"
app:customFloatValue="1" />
</Constraint>
</ConstraintSet>
</MotionScene>
[ ex03_image_filter_view_motion.xml ]
Crossfade 값을 0 > 1 로 변경하여 레이아웃에서 정의한 altSrc 표시
saturation 0 > 1 로 변경하여 레이아웃에서 정의한 src 채도 변경
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.motion.MotionLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutDescription="@xml/ex04_keyframe_motion"
app:showPaths="true"
tools:context=".ex01basic.Ex01BasicActivity">
<View
android:id="@+id/view"
android:layout_width="60dp"
android:layout_height="60dp"
android:background="@color/colorPrimaryRed"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
</android.support.constraint.motion.MotionLayout>
Ex04. 키프레임 애니메이션
[ activity_ex04_key_frame.xml ]
<MotionScene>
<Transition>
<OnSwipe/>
<KeyFrameSet>
<KeyPosition
app:keyPositionType="parentRelative"
app:percentX="0.25"
app:framePosition="50"
app:motionTarget="@+id/view"/>
</KeyFrameSet>
</Transition>
<ConstraintSet android:id='@+id/start'>
<Constraint
android:id="@+id/view"
android:layout_width="60dp"
android:layout_height="60dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</ConstraintSet>
<ConstraintSet android:id="@+id/end">
<Constraint
android:id="@+id/view"
android:layout_width="60dp"
android:layout_height="60dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</ConstraintSet>
</MotionScene>
Ex04. 키프레임 애니메이션
[ ex04_keyframe_motion.xml ]
<MotionScene>
<Transition>
<OnSwipe/>
<KeyFrameSet>
<KeyPosition
app:keyPositionType="parentRelative"
app:percentX="0.25"
app:framePosition="50"
app:motionTarget="@+id/view"/>
</KeyFrameSet>
</Transition>
<ConstraintSet android:id='@+id/start'>
<Constraint
android:id="@+id/view"
android:layout_width="60dp"
android:layout_height="60dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</ConstraintSet>
<ConstraintSet android:id="@+id/end">
<Constraint
android:id="@+id/view"
android:layout_width="60dp"
android:layout_height="60dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</ConstraintSet>
</MotionScene>
Ex04. 키프레임 애니메이션
[ ex04_keyframe_motion.xml ]
50프레임에 부모 뷰를 기준으로 1/4 지점으로 이동시키는 애니메이션
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.motion.MotionLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutDescription="@xml/ex05_keyframe2_motion"
app:showPaths="true"
tools:context=".ex01basic.Ex01BasicActivity">
<View
android:id="@+id/view"
android:layout_width="60dp"
android:layout_height="60dp"
android:background="@color/colorPrimaryRed"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
</android.support.constraint.motion.MotionLayout>
Ex05. 키프레임 애니메이션_2
[ activity_ex05_key_frame2.xml ]
<?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/end"
app:constraintSetStart="@+id/start"
app:duration="1000">
<OnSwipe />
<KeyFrameSet>
<KeyPosition
app:framePosition="20"
app:keyPositionType="parentRelative"
app:motionTarget="@+id/view"
app:percentX="0.1" />
<KeyPosition
app:framePosition="60"
app:keyPositionType="parentRelative"
app:motionTarget="@+id/view"
app:percentX="0.9" />
<KeyAttribute
android:rotation="360"
android:scaleX="2"
android:scaleY="2"
app:framePosition="50"
app:motionTarget="@+id/view" />
</KeyFrameSet>
</Transition>
……
</MotionScene>
Ex05. 키프레임 애니메이션_2
[ ex05_keyframe2_motion.xml ]
<?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/end"
app:constraintSetStart="@+id/start"
app:duration="1000">
<OnSwipe />
<KeyFrameSet>
<KeyPosition
app:framePosition="20"
app:keyPositionType="parentRelative"
app:motionTarget="@+id/view"
app:percentX="0.1" />
<KeyPosition
app:framePosition="60"
app:keyPositionType="parentRelative"
app:motionTarget="@+id/view"
app:percentX="0.9" />
<KeyAttribute
android:rotation="360"
android:scaleX="2"
android:scaleY="2"
app:framePosition="50"
app:motionTarget="@+id/view" />
</KeyFrameSet>
</Transition>
……
</MotionScene>
Ex05. 키프레임 애니메이션_2
[ ex05_keyframe2_motion.xml ]
20, 60프레임에 부모 뷰를 기준으로 10%, 90% 지점으로 이동
50프레임에 뷰의 크기를 2배로 늘리고, 회전하는 애니메이션
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:showPaths="true"
tools:context=".ex06collapsingtoolbar.Ex06CollapsingToolbarActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="@dimen/appbar_height">
<include
layout="@layout/ex06_collapsing_toolbar"/>
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/long_text"
android:textSize="16sp"
android:padding="16dp"
android:lineSpacingMultiplier="1.1"
android:textColor="@color/colorPrimaryBlack"/>
</android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>
Ex06. Collapsing Toolbar
[ activity_ex06_collapsing_toolbar.xml ]
package com.mdlicht.zb.motionlayoutexample.ex06collapsingtoolbar
import android.content.Context
import android.support.constraint.motion.MotionLayout
import android.support.design.widget.AppBarLayout
import android.util.AttributeSet
class CollapsibleToolbar
@JvmOverloads constructor(context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0)
: MotionLayout(context, attrs, defStyleAttr),
AppBarLayout.OnOffsetChangedListener {
override fun onOffsetChanged(appBarLayout: AppBarLayout?, verticalOffset: Int) {
progress = -verticalOffset / appBarLayout?.totalScrollRange?.toFloat()!!
}
override fun onAttachedToWindow() {
super.onAttachedToWindow()
(parent as? AppBarLayout)?.addOnOffsetChangedListener(this)
}
}
Ex06. Collapsing Toolbar
[ CollapsingToolbar.kt ]
<ConstraintSet android:id="@+id/end">
<Constraint
android:id="@+id/background"
android:layout_width="0dp"
android:layout_height="0dp"
android:alpha="0.5"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Constraint
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="0dp"
android:layout_marginStart="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/collapseGuideline" />
<Constraint
android:id="@+id/icon"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginEnd="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/collapseGuideline" />
</ConstraintSet>
</MotionScene>
Ex06. Collapsing Toolbar
[ ex06_collapsing_toolbar_motion ]
<?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/end"
app:constraintSetStart="@+id/start" />
<ConstraintSet android:id='@+id/start'>
<Constraint
android:id="@+id/background"
android:layout_width="0dp"
android:layout_height="0dp"
android:alpha="1.0"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Constraint
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="@+id/icon"
app:layout_constraintStart_toStartOf="@+id/icon"
app:layout_constraintTop_toBottomOf="@+id/icon" />
<Constraint
android:id="@+id/icon"
android:layout_width="80dp"
android:layout_height="80dp"
app:layout_constraintBottom_toTopOf="@+id/name"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed" />
</ConstraintSet>

Android - Motion Layout