In Android development, creating sophisticated and visually appealing user interfaces often involves complex interactions between various components. A classic example is the collapsing toolbar pattern, where the toolbar smoothly collapses or expands as the user scrolls through the content. The CoordinatorLayout and AppBarLayout are key to achieving this effect, especially in XML-based layouts. This post will explore how to use CoordinatorLayout with AppBarLayout in Kotlin for creating collapsing toolbars.
What are CoordinatorLayout and AppBarLayout?
-
CoordinatorLayout:
A super-poweredFrameLayoutthat orchestrates interactions between its child views. It’s particularly useful for implementing complex scrolling behaviors and dependencies among views. -
AppBarLayout:
An extension ofLinearLayoutthat implements many of the concepts and behaviors associated with the action bar. Child views of anAppBarLayoutcan specify scrolling flags to control how they react to scrolling actions.
Why Use CoordinatorLayout and AppBarLayout?
-
Smooth Animations:
Provides smooth and coordinated animations as the user scrolls. -
Complex Scrolling Behaviors:
Enables intricate scrolling effects that enhance user experience. -
Material Design Compliance:
Facilitates the implementation of Material Design principles related to toolbars and scrolling.
Setting Up Your Project
Before diving into the implementation, make sure your project has the necessary dependencies. In your build.gradle file, add the Material Components dependency:
dependencies {
implementation("com.google.android.material:material:1.6.0") // or newer
}
Sync your project after adding the dependency.
Implementing Collapsing Toolbar in XML
To create a collapsing toolbar, you need to structure your XML layout properly. Here’s an example:
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:id="@+id/collapsingToolbar"
android:layout_width="match_parent"
android:layout_height="350dp"
android:fitsSystemWindows="true"
app:contentScrim="?attr/colorPrimary"
app:expandedTitleMarginStart="48dp"
app:expandedTitleMarginEnd="64dp"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<ImageView
android:id="@+id/backdrop"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:scaleType="centerCrop"
android:src="@drawable/your_image"
app:layout_collapseMode="parallax" />
<androidx.appcompat.widget.Toolbar
android:id="@+id/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.core.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="wrap_content"
android:padding="16dp"
android:text="@string/large_text" />
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
Key attributes explained:
-
CoordinatorLayout:
The parent layout that coordinates the behavior of theAppBarLayoutandNestedScrollView. -
AppBarLayout:
Wraps theCollapsingToolbarLayoutand defines the overall behavior of the app bar. -
CollapsingToolbarLayout:
Handles the collapsing and expanding behavior.app:contentScrim="?attr/colorPrimary": Sets the background color of the toolbar when collapsed.app:layout_scrollFlags="scroll|exitUntilCollapsed": Defines how theCollapsingToolbarLayoutshould behave on scrolling.scroll: The view should scroll along with the content.exitUntilCollapsed: The view will collapse until its minimum height is reached.
-
ImageView:
Displays a backdrop image.app:layout_collapseMode="parallax": Makes the image scroll in a parallax effect.
-
Toolbar:
The actual toolbar that displays the title and actions.app:layout_collapseMode="pin": Keeps the toolbar pinned at the top when the layout is collapsed.
-
NestedScrollView:
Allows you to have a scrollable view inside theCoordinatorLayout.app:layout_behavior="@string/appbar_scrolling_view_behavior": Links the scrolling behavior of theNestedScrollViewto theAppBarLayout.
The large_text string can be defined in your strings.xml as a long text to enable scrolling:
<string name="large_text">
<![CDATA[
Lorem ipsum dolor sit amet, consectetur adipiscing elit. ... (Long text here)
]]>
</string>
Implementing in Kotlin
In your Kotlin Activity, you need to set up the toolbar and handle any additional UI interactions.
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.appcompat.widget.Toolbar
import com.google.android.material.appbar.CollapsingToolbarLayout
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val toolbar: Toolbar = findViewById(R.id.toolbar)
setSupportActionBar(toolbar)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
val collapsingToolbar: CollapsingToolbarLayout = findViewById(R.id.collapsingToolbar)
collapsingToolbar.title = "Collapsing Toolbar"
}
}
Explanation:
- Set the Toolbar: Finds the toolbar by its ID and sets it as the support action bar.
- Enable Home Button: Displays the back arrow in the toolbar.
- Set Title: Sets the title of the collapsing toolbar.
Enhancing User Experience
You can further enhance the user experience by adding animations, custom behavior, and more contextual information in the toolbar.
- Dynamic Toolbar Title:
Change the toolbar title based on the scroll position. - Custom Collapse Mode:
Implement custom collapse modes usingViewPropertyAnimatoror other animation techniques. - Adding Menu Items:
Add interactive menu items to the toolbar to provide quick actions.
Example of setting a dynamic toolbar title:
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.appcompat.widget.Toolbar
import com.google.android.material.appbar.CollapsingToolbarLayout
import androidx.core.widget.NestedScrollView
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val toolbar: Toolbar = findViewById(R.id.toolbar)
setSupportActionBar(toolbar)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
val collapsingToolbar: CollapsingToolbarLayout = findViewById(R.id.collapsingToolbar)
collapsingToolbar.title = " " // Start with an empty title
val nestedScrollView: NestedScrollView = findViewById(R.id.nestedScrollView)
nestedScrollView.setOnScrollChangeListener { v, scrollX, scrollY, oldScrollX, oldScrollY ->
if (scrollY > 200) { // Adjust threshold as needed
collapsingToolbar.title = "Collapsing Toolbar"
} else {
collapsingToolbar.title = " " // Keep title empty when at the top
}
}
}
}
Conclusion
Using CoordinatorLayout with AppBarLayout provides a powerful way to create visually appealing and interactive collapsing toolbars in your Android applications. With the flexibility offered by these components, you can achieve complex scrolling behaviors and enhance the overall user experience. By combining the structure in XML with Kotlin code for logic and dynamic updates, you can create robust and elegant solutions.