Search code examples
androidmaterial-designandroid-coordinatorlayout

Android NestedScroll under AppBarLayout


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>

Solution

  • 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