Android NestedScroll under AppBarLayout

Viewed 450

I am trying to use a toolbar with custom shape, and I want to show the text from my NestedScroll under the AppBarLayout.

But I am with some problems as you can see in this screenshot:

enter image description here

How can I achieve this goal?

My XML:

<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"
android:background="@android:color/transparent"
android:animateLayoutChanges="true">

<com.google.android.material.appbar.AppBarLayout
    android:id="@+id/appbar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    android:background="@null"
    app:elevation="0dp">

    <androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="94dp"
        android:background="@drawable/background_header_asset"
        app:layout_collapseMode="pin"/>
</com.google.android.material.appbar.AppBarLayout>

<androidx.core.widget.NestedScrollView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior">

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


</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

PS.: the toolbar background is a drawable shape, so its transparent

Edit:

My shape is:

<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="320dp"
android:height="94dp"
android:viewportWidth="320"
android:viewportHeight="94">
<path
  android:pathData="M320,73.153L81.283,92.257C64.54,93.42 54.316,94 
  50.612,94c-3.705,0 -8.826,-1.771 -15.363,-5.314L0,70.176V0h320v73.153z"
  android:fillColor="#01874D"
  android:fillType="evenOdd"/>
 </vector>
4 Answers

You can get the look you want by breaking the current toolbar into two pieces:

  1. An ordinary rectangular toolbar, that works as usual
  2. A custom shape that's anchored to the bottom of the toolbar.

First, make a smaller vector drawable (30dp high, representing just the bottom of your original shape):

<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="320dp"
android:height="30dp"
android:viewportWidth="320"
android:viewportHeight="30">
<path
  android:pathData="M320,9.153 L81.283,28.257C64.54,29.42 54.316,30 50.612,30 46.907,30 41.786,28.229 35.249,24.686L0,6.176V0h320z"
  android:strokeWidth="0.999999"
  android:fillColor="#01874d"
  android:fillType="evenOdd"/>
</vector>

Then, just use a standard rectangular toolbar of fixed height (64dp to make it look like before).

Finally, add a FrameLayout after your NestedScrollView, and anchor it to the bottom of your appbar:

<FrameLayout
    android:id="@+id/customShapeOverlay"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@drawable/background_header_asset"
    app:layout_anchor="@id/appbar"
    app:layout_anchorGravity="bottom"
    android:layout_gravity="bottom"/>

The FrameLayout is just there as a container for your custom shape. Because it's added to the parent CoordinatorLayout after the NestedScrollView, it will overlay that view (as desired).

Here's the complete layout xml:

<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:background="@android:color/transparent"
android:animateLayoutChanges="true">
<com.google.android.material.appbar.AppBarLayout
    android:id="@+id/appbar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    android:background="@null"
    app:elevation="0dp">
    <androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="64dp"
        android:background="@color/colorPrimary"
        app:layout_collapseMode="pin"/>
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior">
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="32dp"
        android:text="@string/ipsun" />
</androidx.core.widget.NestedScrollView>
<FrameLayout
    android:id="@+id/customShapeOverlay"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@drawable/background_header_asset"
    app:layout_anchor="@id/appbar"
    app:layout_anchorGravity="bottom"
    android:layout_gravity="bottom"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

The resulting layout looks like this:

Custom toolbar overlaying scrolled text

  1. Have you tried to change this: android:background="@null" into this android:background="@android:color/transparent"? It can make a difference in some situations.
  2. Could you show the xml for your shape? Are you sure there is no white background?
  3. What color of toolbar have you chose for the app main style? Is it white? I am trying to reduce number of posssible problem sources.

My guess is that CoordinatorLayout puts NestedScrollView below your AppBarLayout because of ScrollingViewBehavior. And it renders only inside its borders

Try adding android:clipToPadding="false" to NestedScrollView

You can try this one without CoordinatorLayout

<?xml version="1.0" encoding="utf-8"?>
<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.core.widget.NestedScrollView
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:clipToPadding="false"
       android:paddingTop="94dp"
       app:layout_constraintTop_toTopOf="parent">

       <TextView
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
           android:text="@string/ipsun"/>
   </androidx.core.widget.NestedScrollView>

   <androidx.appcompat.widget.Toolbar
       android:id="@+id/toolbar"
       android:layout_width="match_parent"
       android:layout_height="94dp"
       android:background="@drawable/background_header_asset"
       app:layout_constraintTop_toTopOf="parent" /> 
</androidx.constraintlayout.widget.ConstraintLayout>

The main think here:

  • Toolbar under NestedScrollView else text will be on toolbar (looks like green area transparent)
  • android:clipToPadding="false"
  • android:paddingTop="94dp" padding value must be equals for tollbar height
Related