Skip to content
Advertisement

CoordinatorLayout with NestedScrollView adding padding bottom for sticky button not working

I have this scenario :

I’ve created this

<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>

Then here’s my 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>

Then I’m doing the collapsing animation as :

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
        }
    }
})

It works flawless, the problem is now that I want to add a sticky button but I can not tell to NestedScrollView to be aligned bottomToTopOf my button because it’s not inside a ConstraintLayout neither it’s a child of it, so it doesn’t crash in terms of compiling but the button hides the last part of the scrollView… I’ve tried to add marginBottom="buttonSize" and in the layout design it looks good, but when compiling it doesn’t do the collapsing animation because I’ve added the marginBottom. How can I fix this? I need this NestedScrollView to be not height match_parent even if it’s wrap_content it’s aligned to the parent and the button is overlapped.

Advertisement

Answer

You can wrap the CoordinatorLayout & the bottom Button inside a ConstraintLayout as the root layout; now the CoordinatorLayout can be constraint to the top of the button instead of having a height that equals to the entire screen height.

So, the layout would be:

<ConstraintLayout>

    <CoordinatorLayout>
        <AppBarLayout>
            <CollapsingToolbarLayout>
        <NestedScrollView>
    </CoordinatorLayout>
    
    <Button/>
    
</ConstraintLayout>

Applying to your layout:

<androidx.constraintlayout.widget.ConstraintLayout 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">

    <androidx.coordinatorlayout.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintBottom_toTopOf="@+id/button"
        app:layout_constraintTop_toTopOf="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">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/long_text" />

        </androidx.core.widget.NestedScrollView>

    </androidx.coordinatorlayout.widget.CoordinatorLayout>


    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        android:insetLeft="0dp"
        android:text="OK"
        android:insetTop="0dp"
        android:insetRight="0dp"
        android:insetBottom="0dp"
        app:layout_constraintBottom_toBottomOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
Advertisement