Search code examples
androidkotlinandroid-layoutandroid-toolbarandroid-collapsingtoolbarlayout

How can I update the toolbar when scrolling with CollapsingToolbar


I'm trying to move from one TextView to the Toolbar when it collapse when scrolling.

Let's say I have a Toolbar and just below of it I have a View, when I scroll up and it starts to not be visible at all I want to update the toolbar with this text, here's an example.

First Scenario enter image description here

Second Scenario enter image description here

I've been reading with the CollapsingToolbar but I can figure it out when the view is not that visible and if I have to create like a custom Toolbar with a text at the right where I can set, because it's not the title, it's an extra value of the title.


Solution

  • where I can set, because it's not the title, it's an extra value of the title.

    You can use the title for a customized Toolbar as supportActionBar; but adjust the scrolling flags appropriately to the toolbar & the layout behaviour to the main layout.

    if I have to create like a custom Toolbar with a text at the right

    To set the title to the right; there are 2 properties, one for the collapsed text, and the other for the expanded, you need to align them to the end/right:

    app:collapsedTitleGravity="end"
    app:expandedTitleGravity="end"
    

    Here is a demo:

    <?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/appbarlayout"
            android:layout_width="match_parent"
            android:layout_height="100dp"
            android:paddingEnd="8dp"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
    
            <com.google.android.material.appbar.CollapsingToolbarLayout
                android:id="@+id/collapsing_toolbar"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                app:collapsedTitleGravity="end"
                app:contentScrim="?attr/colorPrimary"
                app:expandedTitleGravity="end"
                app:layout_scrollFlags="scroll|exitUntilCollapsed"
                app:title="Hi">
    
                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:orientation="vertical"
                    app:layout_collapseMode="parallax" />
    
                <androidx.appcompat.widget.Toolbar
                    android:id="@+id/toolbar"
                    android:layout_width="match_parent"
                    android:layout_height="?attr/actionBarSize"
                    app:layout_collapseMode="pin"
                    app:layout_scrollFlags="scroll|enterAlways|snap"
                    app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
                    app:title="Hi"
                    app:titleTextColor="#fff" />
    
            </com.google.android.material.appbar.CollapsingToolbarLayout>
    
        </com.google.android.material.appbar.AppBarLayout>
    
    
        <!--    Main Layout -->
    
        <androidx.core.widget.NestedScrollView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_behavior="@string/appbar_scrolling_view_behavior"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/appbarlayout">
    
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/long_text" />
    
        </androidx.core.widget.NestedScrollView>
    
    
    </androidx.coordinatorlayout.widget.CoordinatorLayout>
    

    Make sure to use a NoActionBar theme, and set the custom Toolbar as the supportActionBar:

    val toolbar = findViewById<Toolbar>(R.id.toolbar)
    setSupportActionBar(toolbar)
    

    Update:

    perhaps I missexplained the issue, the thing is, I have a Toolbar and just below, I have like a LinearLayout with Text, and when I scroll and this LinearLayout is going to hide I want to show the text it was in the LinearLayout. So the idea is, Something like you did, but instead of having this "Hi" in the Toolbar, have it in a view just below the Toolbar and when I scroll and it starts to get invisible / non readable just put this "Hi" text in the Toolbar.

    You can do this with a customized TextView & the title of the CollapsingToolBar.. and programmatically toggle the visibility on both with the OnOffsetChangedListener

    First, create the below styles fol collapsed & expanded states:

        <style name="Title.Collapsed" parent="android:TextAppearance">
            <item name="android:textColor">@android:color/white</item>
            <item name="android:textSize">18sp</item>
        </style>
    
        <style name="Title.Expanded" parent="android:TextAppearance">
            <item name="android:textColor">@android:color/white</item>
            <item name="android:textSize">28sp</item>
        </style>
    

    These styles will be applied to app:collapsedTitleTextAppearance & app:expandedTitleTextAppearance on the CollapsingToolbarLayout respectively.

    layout:

    <?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">
    
        <com.google.android.material.appbar.AppBarLayout
            android:id="@+id/appBarLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@android:color/transparent"
            android:fitsSystemWindows="true"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light">
    
            <com.google.android.material.appbar.CollapsingToolbarLayout
                android:id="@+id/collapsingToolbar"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:fitsSystemWindows="true"
                app:collapsedTitleGravity="end"
                app:collapsedTitleTextAppearance="@style/Title.Collapsed"
                app:expandedTitleGravity="end"
                app:expandedTitleMarginEnd="64dp"
                app:expandedTitleMarginStart="48dp"
                app:expandedTitleTextAppearance="@style/Title.Expanded"
                app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">
    
                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:layout_marginTop="40dp"
                    android:background="@android:color/transparent"
                    android:gravity="end"
                    android:orientation="vertical"
                    android:padding="10dp"
                    app:layout_collapseMode="parallax">
    
                    <TextView
                        android:id="@+id/tv_title"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="Hi"
                        android:textSize="28sp" />
                </LinearLayout>
    
                <androidx.appcompat.widget.Toolbar
                    android:id="@+id/toolbar"
                    android:layout_width="match_parent"
                    android:layout_height="?attr/actionBarSize"
                    android:background="@color/design_default_color_primary"
                    app:layout_collapseMode="pin"
                    app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
    
            </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"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/appBarlayout">
    
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/long_text" />
    
        </androidx.core.widget.NestedScrollView>
    
    </androidx.coordinatorlayout.widget.CoordinatorLayout>
    

    The detect the appBarLayout scrolling change in addOnOffsetChangedListener:

    val collapsingToolbar = findViewById<CollapsingToolbarLayout>(R.id.collapsingToolbar)
    collapsingToolbar.title = ""
    title = ""
    
    val appBarLayout = findViewById<AppBarLayout>(R.id.appBarLayout)
    appBarLayout.addOnOffsetChangedListener(object : OnOffsetChangedListener {
        var isShow = false
        var scrollRange = -1
        override fun onOffsetChanged(appBarLayout: AppBarLayout, verticalOffset: Int) {
            if (scrollRange == -1) {
                scrollRange = appBarLayout.totalScrollRange
            }
            if (scrollRange + verticalOffset == 0) {
                //when collapsingToolbar at that time display actionbar title
                collapsingToolbar.title = "Hi"
                isShow = true
            } else if (isShow) {
                collapsingToolbar.title = ""
                isShow = false
            }
        }
    })