Collapsing Toolbar | Android | XML
Demo
In this article, I will be showing you how to create a collapsing toolbar with an image and a nested scroll view. It is a very appealing feature to add to your application so let’s get started :)
First, we will make the status bar black and get rid of the action bar.
- Go to themes.xml in the res/values/themes folder and change the status bar color to black and the parent theme to NoActionBar.
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.CollapsingToolbar" parent="Theme.MaterialComponents.DayNight.NoActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_500</item>
<item name="colorPrimaryVariant">@color/purple_700</item>
<item name="colorOnPrimary">@color/white</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/teal_200</item>
<item name="colorSecondaryVariant">@color/teal_700</item>
<item name="colorOnSecondary">@color/black</item>
<!-- Status bar color. -->
<item name="android:statusBarColor">@color/black</item>
<!-- Customize your theme here. -->
</style>
</resources>
Now, on to the good stuff.
- Go to your fragment or activity where you want this feature implemented and make sure it’s a Coordinator Layout.
- Inside the Coordinator Layout, add an App Bar Layout. And inside the App Bar Layout you will add the Collapsing Toolbar Layout. The layout scroll flags will be scroll, exitUntilCollapsed and enterAlwaysCollapsed. Later in the article, I will show you what these scroll flags mean.
- Inside the Collapsing Toolbar Layout, we will be adding an image and the toolbar. This is what is shown at the top of the screen and what will be collapsed when the user scrolls down.
This should be your code so far..
<?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:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="300dp"
app:layout_scrollFlags="scroll|exitUntilCollapsed|enterAlwaysCollapsed">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:keepScreenOn="true"
android:src="@drawable/unsplash_image"
app:layout_collapseMode="parallax"/>
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
app:title="Toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:layout_collapseMode="pin"/>
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
Then you want to enable viewBinding and add the setSupportActionBar() inside onCreate() in your activity.
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
binding = ActivityMainBinding.inflate(layoutInflater)
setSupportActionBar(binding.toolbar)
}
}
Under the App Bar Layout, we will add a Nested Scroll View with some text views. But first lets create the background for the Nested Scroll View.
- Create a new drawable resource file in res/drawable.
- We want to add top corner radius to curve the corners.
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/black"/>
<corners android:topLeftRadius="20dp"
android:topRightRadius="20dp"/>
</shape>
Now let’s add a Nested Scroll View below the App Bar Layout with some text views. There are 3 things that I added to the Nested Scroll View.
- First, I added a top margin of -20dp because I want the nested scroll view to be overlapping on top of the image.
- You NEED to add the app_bar_scrolling_view_behavior in order for this to work.
- I added some random Lorem Ipsum text to the text view.
<?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:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="300dp"
app:layout_scrollFlags="scroll|exitUntilCollapsed|enterAlwaysCollapsed">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:keepScreenOn="true"
android:scaleType="centerCrop"
android:src="@drawable/unsplash_image"/>
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="-20dp"
android:background="@drawable/nested_scroll_background"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris viverra urna eu gravida hendrerit. Suspendisse lobortis non turpis vel ullamcorper. Ut dolor odio, sagittis vel pellentesque sed, ultrices quis nunc. Aliquam porttitor imperdiet malesuada. Fusce dapibus lobortis accumsan. In faucibus sollicitudin enim vitae aliquet. Aliquam ut euismod ipsum. Praesent at ullamcorper erat. Nunc accumsan ipsum in elit molestie ullamcorper. Nullam finibus sed ante id feugiat. Praesent eu malesuada lacus. Sed eu massa lobortis ante laoreet vestibulum ac non arcu.\n\nProin malesuada lacus vel nulla consequat dignissim. Praesent tempus, felis at aliquet interdum, metus mauris venenatis erat, vel tempor ipsum justo vel orci. Nullam ipsum justo, elementum vitae libero in, tempus ornare libero. Aenean venenatis euismod massa, vitae ornare justo laoreet iaculis. In non consequat enim, vel finibus mi. Vestibulum congue gravida lacinia. Suspendisse potenti. Proin dignissim, purus in tristique vehicula, ipsum enim blandit neque, non ornare ex diam quis tortor. Aenean vestibulum, metus vel sollicitudin euismod, purus lacus condimentum mi, eu mattis dui turpis nec lectus. Duis eget dolor id magna lobortis bibendum. Proin in sem metus. Sed a mattis felis. Quisque luctus auctor justo vel porttitor. In efficitur mattis rhoncus.\n\nAliquam vel pulvinar lacus. Etiam aliquet turpis lacus, at auctor erat efficitur in. Vestibulum consequat elit libero, vel semper enim ultricies malesuada. Ut eu sollicitudin turpis. Aliquam volutpat ante ut commodo interdum. Curabitur pharetra, urna quis viverra placerat, sem nisi maximus elit, vel finibus elit felis non magna. Proin pretium, nisi malesuada lacinia vestibulum, nunc velit tempor augue, venenatis aliquet ante nisl in metus. Donec ultricies mauris efficitur dui convallis auctor. Vestibulum fringilla orci ligula, at pretium neque iaculis tempor. Vestibulum semper, libero vitae tincidunt rhoncus, neque lorem tincidunt dolor, ut tempor orci sem eu felis. Donec quis tempor diam. Suspendisse ornare, mi dapibus molestie finibus, sapien eros rhoncus velit, id pharetra elit odio et ipsum. Cras vitae augue eget nulla hendrerit volutpat. Nulla facilisis purus eu justo cursus cursus."
app:layout_constraintTop_toTopOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
This is the final code and if you run the app, it should look like this..
Scroll Flags
Now I will demonstrate how you can use different scroll flags to get different scrolling actions.
Scroll & Enter Always
app:layout_scrollFlags="scroll|enterAlways"
Scroll & Enter Always Collapsed
app:layout_scrollFlags="scroll|enterAlwaysCollapsed"
Scroll & Snap
app:layout_scrollFlags="scroll|snap"
Scroll & Exit Until Collapsed
app:layout_scrollFlags="scroll|exitUntilCollapsed"
Conclusion
There are many ways that you can change the animations of the collapsing toolbar. This is an awesome feature that you can add to your application. I have added it to my own application in the Google Play Store called “My PR Tracker”.
https://play.google.com/store/apps/details?id=com.alexp.myprtracker
GitHub Repository
Let me know if you have any questions. Happy coding!