constraintlayout
constraintlayout copied to clipboard
MotionLayout animation issue when recyclerview scrolling
We have been working on an android project, and we faced with a problem in animation into the motionLayout when recyclerView is scrolling (you can see in video).
after scroll in anywhere on screen animation is fine but after scroll recyclerview appBar animation is run but so weird.
I added picture and video from UI architect to avoid confusion.
ProfileFragment.kt
private fun coordinateMotion() {
val appBarLayout: AppBarLayout? = binding.appbarLayout
val motionLayout: MotionLayout = binding.profileHeaderInfo as MotionLayout
val p = DecimalFormat("0.0");
val listener = AppBarLayout.OnOffsetChangedListener { unused, verticalOffset ->
val seekPosition = -verticalOffset / appBarLayout?.totalScrollRange!!.toFloat()
motionLayout.progress = seekPosition
Log.d(TAG, "coordinateMotion: $seekPosition")
}
appBarLayout?.addOnOffsetChangedListener(listener)
}
ProfileFragment:
<?xml version="1.0" encoding="utf-8"?>
<layout 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">
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:fillViewport="true"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<include
android:id="@+id/profile_include"
layout="@layout/profile_layout_content" />
</androidx.core.widget.NestedScrollView>
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.constraintlayout.motion.widget.MotionLayout
android:id="@+id/profile_header_info"
android:layout_width="match_parent"
app:motionDebug="SHOW_PATH"
android:layout_height="wrap_content"
android:minHeight="80dp"
android:background="@color/primary"
app:layout_scrollFlags="scroll|enterAlways|snap|exitUntilCollapsed"
app:layoutDescription="@xml/fragment_profile_xml_profile_header_info_scene"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
.....
</androidx.constraintlayout.motion.widget.MotionLayout>
</com.google.android.material.appbar.AppBarLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
fragment_profile_xml_profile_header_info_scene.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">
<ConstraintSet android:id="@+id/start">
<Constraint
android:id="@+id/profile_user_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="24dp"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintStart_toEndOf="@+id/profile_image"
motion:layout_constraintTop_toTopOf="@+id/profile_image">
</Constraint>
<Constraint
android:id="@+id/profile_user_login"
android:layout_width="0dp"
android:layout_height="wrap_content"
motion:layout_constraintBottom_toTopOf="@+id/profile_user_desc"
motion:layout_constraintEnd_toEndOf="@+id/profile_user_name"
motion:layout_constraintStart_toStartOf="@+id/profile_user_name"
motion:layout_constraintTop_toBottomOf="@+id/profile_user_name">
</Constraint>
<Constraint
android:id="@+id/profile_user_desc"
android:layout_width="0dp"
android:layout_height="wrap_content"
motion:layout_constraintBottom_toBottomOf="@+id/profile_image"
motion:layout_constraintEnd_toEndOf="@+id/profile_user_login"
motion:layout_constraintStart_toStartOf="@+id/profile_user_login"
motion:layout_constraintTop_toBottomOf="@+id/profile_user_login" />
<Constraint
android:id="@+id/profile_image"
android:layout_width="75dp"
android:layout_height="75dp"
android:layout_marginStart="24dp"
android:layout_marginTop="24dp"
android:layout_marginEnd="16dp"
android:elevation="10dp"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintHorizontal_bias="0.0"
motion:layout_constraintStart_toStartOf="parent"
motion:layout_constraintTop_toTopOf="parent" />
</ConstraintSet>
<ConstraintSet android:id="@+id/end">
<Constraint
android:id="@+id/profile_user_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
motion:layout_constraintStart_toEndOf="@+id/profile_image"
motion:layout_constraintTop_toTopOf="@+id/profile_image">
<CustomAttribute
motion:attributeName="textSize"
motion:customDimension="10sp" />
</Constraint>
<Constraint
android:id="@+id/profile_user_login"
android:layout_width="0dp"
android:layout_height="wrap_content"
motion:layout_constraintBottom_toBottomOf="@id/profile_user_name"
motion:layout_constraintStart_toEndOf="@+id/profile_user_name"
motion:layout_constraintTop_toTopOf="@id/profile_user_name"
motion:layout_constraintEnd_toEndOf="parent">
<CustomAttribute
motion:attributeName="textSize"
motion:customDimension="8sp" />
</Constraint>
<Constraint
android:id="@+id/profile_user_desc"
android:layout_width="0dp"
android:layout_height="wrap_content"
motion:layout_constraintBottom_toBottomOf="@+id/profile_image"
motion:layout_constraintEnd_toEndOf="@+id/profile_user_login"
motion:layout_constraintStart_toStartOf="@+id/profile_user_name"
motion:layout_constraintTop_toBottomOf="@+id/profile_user_name" />
<Constraint
android:id="@+id/profile_image"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginStart="24dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp"
android:elevation="10dp"
motion:layout_constraintBottom_toBottomOf="parent"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintHorizontal_bias="0.0"
motion:layout_constraintStart_toStartOf="parent"
motion:layout_constraintTop_toTopOf="parent" />
<Constraint
android:id="@+id/profile_header_divider"
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_marginTop="0dp"
motion:layout_constraintEnd_toEndOf="@+id/profile_user_desc"
motion:layout_constraintStart_toStartOf="@+id/profile_image"
motion:layout_constraintTop_toBottomOf="@+id/profile_user_desc" />
<Constraint
android:id="@+id/profile_header_company_icon"
android:layout_width="20dp"
android:layout_height="20dp"
motion:layout_constraintStart_toStartOf="@+id/profile_header_divider"
motion:layout_constraintTop_toTopOf="parent" />
</ConstraintSet>
<Transition
motion:constraintSetEnd="@+id/end"
motion:constraintSetStart="@id/start"
motion:duration="1000">
<KeyFrameSet>
<KeyAttribute
android:alpha="0"
motion:framePosition="100"
motion:motionTarget="@+id/profile_header_divider" />
</KeyFrameSet>
<KeyFrameSet>
<!-- <KeyAttribute-->
<!-- android:alpha="0"-->
<!-- motion:framePosition="100"-->
<!-- motion:motionTarget="@+id/profile_user_desc" />-->
<KeyAttribute
android:alpha="0"
motion:framePosition="100"
motion:motionTarget="@+id/profile_header_company" />
<KeyAttribute
android:alpha="0"
motion:framePosition="100"
motion:motionTarget="@+id/profile_header_location" />
<KeyAttribute
android:alpha="0"
motion:framePosition="100"
motion:motionTarget="@+id/profile_header_create_at" />
<KeyAttribute
android:alpha="0"
motion:framePosition="100"
motion:motionTarget="@+id/profile_header_company_icon" />
<KeyAttribute
android:alpha="0.0"
motion:framePosition="100"
motion:motionTarget="@+id/profile_header_location_icon" />
<KeyAttribute
android:alpha="0"
motion:framePosition="100"
motion:motionTarget="@+id/profile_header_create_at_icon" />
</KeyFrameSet>
<OnSwipe />
</Transition>
</MotionScene>
A few issues KeyFrames are for modifying the behavior between states. You seem to be trying to change the end constraintSet by using KeyFrames. That will lead to bugs. Generally motion:framePosition="100" is a bug except in complex situations. It is creating a difference between the final state (The ConstraintSet) and the transitions final state the (KeyAttributes)
add "android:alpha="0" to the end constraintsets's constraints
Also
You probably do not want the <OnSwipe>
CoordnatorLayout is driving the animation.
See MotionLayout examples
hi @jafu888 thanks for your help.
as you said, I deleted all KeyFrameSets and set android:alpha="0" in constraints. also i delete <OnSwip>
, coordnatorLayout is driving the animation. But the problem remains.
Your code looks almost exactly like the example. The only thing I see odd is you set android:layout_height="wrap_content"
Not match parent
android:layout_height="match_parent"
Try that?