mrobinson7627 mrobinson7627 - 3 months ago 43
Android Question

Android CoordinatorLayout Behaviour with complex layout

I have a simple layout that is a

CoordinatorLayout
containing a
Toolbar
in an
AppBarLayout
and a
RecyclerView
. To allow for a progress bar while content is loaded into the
RecyclerView
I've wrapped it in a
FrameLayout
alongside a
ProgressBar
which I've included from another file. When the content is loading the
ProgressBar
is set to
VISIBLE
and when it's finished it's set to
GONE
, showing the
RecyclerView
. I'd like to use a
ScrollingViewBehavior
so that when I scroll my
RecyclerView
the
Toolbar
is hidden. I've tried adding it to the
FrameLayout
and the
RecyclerView
and neither seems to work.

What do I have to do to get the behavior I am looking for? Do I need to make a new
ViewGroup
or something like that in order to show/hide the
ProgressBar
and define a new
Behavior
for that, or is there something simpler?

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">

<android.support.design.widget.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content">

<android.support.v7.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize"
android:theme="@style/ToolbarTheme"
android:background="?attr/colorPrimary"/>
</android.support.design.widget.AppBarLayout>

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
android:layout_width="match_parent"
android:layout_height="match_parent">

<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"
android:id="@+id/recycler_view" />

<include layout="@layout/progress_circle" />

</FrameLayout>

<include layout="@layout/floating_action_button"/>
</android.support.design.widget.CoordinatorLayout>

Answer

I have almost the same setup you do, but I've included two progress bars. One appears when the activity is loaded, and covers the whole thing. The second one appears on a swipe refresh and only replaces the RecyclerView (well, actually the RecyclerView's parent SwipeRefreshLayout).

<RelativeLayout
    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:focusableInTouchMode="true">

    <include layout="@layout/loading_progress"/>

    <android.support.design.widget.CoordinatorLayout
        android:id="@+id/coordinator_layout"
        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="false">

        <android.support.design.widget.AppBarLayout
            android:id="@+id/app_bar"
            android:layout_width="match_parent"
            android:layout_height="@dimen/app_bar_height"
            android:fitsSystemWindows="false"
            android:theme="@style/AppTheme.AppBarOverlay">

            <android.support.design.widget.CollapsingToolbarLayout
                android:id="@+id/toolbar_layout"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:fitsSystemWindows="false"
                app:contentScrim="?attr/colorPrimary"
                app:layout_scrollFlags="scroll|enterAlways">

                <android.support.v7.widget.Toolbar
                    android:id="@+id/toolbar_landing_page"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    app:layout_collapseMode="pin"
                    app:popupTheme="@style/AppTheme.PopupOverlay"/>

            </android.support.design.widget.CollapsingToolbarLayout>
        </android.support.design.widget.AppBarLayout>

        <include layout="@layout/loading_progress"/>

        <android.support.v4.widget.SwipeRefreshLayout
            android:id="@+id/swipe_refresh"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_marginTop="@dimen/landing_page_top_margin"
            app:layout_behavior="@string/appbar_scrolling_view_behavior">

            <android.support.v7.widget.RecyclerView
                android:id="@+id/recycler_view"
                android:layout_width="match_parent"
                android:layout_height="match_parent"/>

        </android.support.v4.widget.SwipeRefreshLayout>
    </android.support.design.widget.CoordinatorLayout>
</RelativeLayout>

And my progress bar is just:

<ProgressBar
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/loading_progress"
    style="@android:style/Widget.ProgressBar.Inverse"
    android:layout_centerHorizontal="true"
    android:layout_centerVertical="true"
    android:visibility="gone"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>

When it's time to show the progress bar I set it to View.VISIBLE and the SwipeRefreshLayout (or the CoordinatorLayout for when the Activity is loaded) to View.GONE. Then reverse the VISIBLE and GONE when the data is loaded.