Round corners animation
One of my screens has collapsible header with tabs, and designer made rounded corners for tabs. But how it should look in collapsed state? I decided to implement animation, which I saw in bottom sheet in another app. It should look like this:
Layout file:
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.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"
tools:context=".MainActivity">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/purple_200">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="@dimen/header_height"
app:layout_scrollFlags="snap|scroll">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Header"
android:textColor="@color/white"
android:textSize="30sp" />
</FrameLayout>
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="@dimen/tabs_height"
android:background="@color/white"
app:layout_scrollFlags="noScroll">
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Tab1" />
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Tab2" />
</com.google.android.material.tabs.TabLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="24dp"
android:text="Content"
android:textColor="@color/black"
android:textSize="30sp" />
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
We will use MaterialShapeDrawable from Material components library. To import it add this line to build.gradle file:
implementation 'com.google.android.material:material:1.3.0'
Now we create background drawable with 2 round corners for TabLayout.
// Create background drawable for TabLayout
val shapeAppearanceModel = ShapeAppearanceModel()
.toBuilder()
.setTopLeftCornerSize(cornerSize)
.setTopRightCornerSize(cornerSize)
.build()
val materialShapeDrawable = MaterialShapeDrawable(shapeAppearanceModel).apply {
fillColor = ColorStateList.valueOf(Color.WHITE)
}
ViewCompat.setBackground(tabs, materialShapeDrawable)
And finally, we are animating corners. MaterialShapeDrawable will make all job for us. It has interpolation property, which documentation says: “Set the interpolation of the path, between 0 and 1. Ranges between 0 (none) and 1 (fully) interpolated. An interpolation of 1 generally indicates a fully rendered path, while an interpolation of 0 generally indicates a fully healed path, which is usually a rectangle.” So, we’ll change this property in range from 1 for round corners to 0 for rectangle.
// Listen AppBarLayout for scroll
appbar.addOnOffsetChangedListener(AppBarLayout.OnOffsetChangedListener { appBarLayout, verticalOffset ->
val collapsedHeight = appBarLayout.height - tabs.height
val collapsePercent = -verticalOffset.toFloat() / collapsedHeight
// set shape interpolation: 1 is fully rounded, 0 is rectangle
materialShapeDrawable.interpolation = 1 - collapsePercent
})
It’s not so hard when you have right library, right? :)