14

I have the design provided at the bottom.

The things I want to happen above the tabs layout:

  1. I want to have an AppBarLayout which hides when the user scrolls down on the RecyclerView in one of the tabs.
  2. I want the user image to be attached to the blue background behind it and to hide when the user scrolls down.
  3. I want the tabs to be pinned at the top when the user scrolls so he can easily switch them. The recycler view and the tabs layout must be the only things visible to the user when he scrolls down.

So I did achieve 1 and 3, but I cannot achieve 2 - when you scroll slowly the RecyclerView the image stays over it and does not hide.

Here are the things I have done:

  1. I did implement the coordinator layout only in the fragment, which is displayed here. It is not implemented in a new activity or in the activity which hosts the fragment and the fragment does not have a toolbar. That means I am using a CollapsingToolbarLayout without a toolbar in it.
  2. I am using a floating action button from the support design library to display the user image. I use it because when it hides it does it with animation.

Check the XML at the bottom.

So what happens:

  1. Everything loads perfectly
  2. The button is attached at the correct position
  3. The AppBarLayout responds to scroll
  4. When scrolling slowly the button is not hiding
  5. When scrolling fast it does hide
  6. When changing viewpager fragments it does hide

Here is a video with the problem: YOUTUBE

I tried to debug the CoordinatorLayout and when it called the hide() method of the button but I couldn't find the problem. Any ideas?

Edit 1:

If you remove the toolbar in the cheesesquare example you will get the same bug.

My test xml:

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

    <android.support.design.widget.AppBarLayout
        android:id="@+id/app_bar_layout"
        android:elevation="1dp"
        android:fitsSystemWindows="true"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

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

            <ImageView
                android:id="@+id/img"
                android:src="@drawable/header_bg"
                android:scaleType="centerCrop"
                android:cropToPadding="true"
                app:layout_collapseMode="parallax"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />

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


    <android.support.v4.view.ViewPager
        android:id="@+id/profile_tabs"
        android:elevation="2dp"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/test"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:elevation="1dp"
        app:pressedTranslationZ="12dp"
        android:clickable="true"
        app:rippleColor="@android:color/transparent"
        android:src="@drawable/ic_launcher"
        app:layout_collapseMode="parallax"
        app:layout_anchor="@id/app_bar_layout"
        app:layout_anchorGravity="bottom|left|end" />

</android.support.design.widget.CoordinatorLayout>

Sample design

Edit 2:

There is also an issue marked as Declined for this problem.

rciovati
  • 27,603
  • 6
  • 82
  • 101
NMP
  • 490
  • 1
  • 5
  • 17
  • Yes, the problem is that the coordinator layout is not working as expected. It just needs to have a toolbar to detect the changes. – NMP Sep 21 '15 at 05:38

5 Answers5

7

You have to implement custom behavior for FAB to achieve effect which you want. I slightly changed original implementation, to get it working without toolbar.

    public class FABBehavior extends FloatingActionButton.Behavior {

    public FABBehavior() {
    }

    public FABBehavior(Context context, AttributeSet attributeSet) {
    }

    public boolean onDependentViewChanged(CoordinatorLayout parent, FloatingActionButton child, View dependency) {
        if(dependency instanceof Snackbar.SnackbarLayout) {
           return super.onDependentViewChanged(parent, child, dependency);
        } else if(dependency instanceof AppBarLayout) {
            this.updateFabVisibility(parent, (AppBarLayout)dependency, child);
        }

        return false;
    }

    private boolean updateFabVisibility(CoordinatorLayout parent, AppBarLayout appBarLayout, FloatingActionButton child) {
        CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams)child.getLayoutParams();
        if(lp.getAnchorId() != appBarLayout.getId()) {
            return false;
        } else {

            ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) child.getLayoutParams();
            int point = child.getTop() - params.topMargin;
            try {
                Method method = AppBarLayout.class.getDeclaredMethod("getMinimumHeightForVisibleOverlappingContent");
                method.setAccessible(true);
                if(point <= (int) method.invoke(appBarLayout)) {
                    child.hide();
                } else {
                    child.show();
                }
                return true;
            } catch (Exception e) {
                return true;
            }
        }
    }
}

You may apply this behavior using app:layout_behavior of course.

dtx12
  • 4,438
  • 1
  • 16
  • 12
  • 1
    ok, seems like author doesn't check answers, not sure about point of this question. – dtx12 Sep 17 '15 at 15:11
  • 1
    Wow, great! This works, it has little issues when you scroll slowly but it is not a problem. I thought that it was too hard to be done. GREAT JOB! THANKS A LOT! – NMP Sep 21 '15 at 05:56
  • As @NMP mentioned it's work but when you scroll slowly FAB appears again ! did you have any idea about this ? – Amir Jan 11 '16 at 21:00
  • Could you please post your layout? – erdna Apr 08 '16 at 08:46
2

I had similar issue and I fixed it as shown below:

AppBarLayout appBarLayout = (AppBarLayout)findViewById(R.id.app_bar_layout);
    appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
        @Override
        public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
            if(fab.getTop() <= 0) {
                fab.hide();
            } else {
                fab.show();
            }
        }
    });

I have this code inside activity class and I am running this code on Lollipop.

Varini Ramesh
  • 251
  • 1
  • 4
-1

I used this code in my app:

<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/circlejoined_rootview"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.CoordinatorLayout
    android:id="@+id/circlebd_rootview"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="@dimen/collapsing_height"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/collapsingToolbarLayout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:contentScrim="?attr/colorPrimary"
            app:layout_scrollFlags="scroll|exitUntilCollapsed"
            app:expandedTitleTextAppearance="@style/expanded_title">

            <ImageView
                android:id="@+id/circleback_img"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:scaleType="centerCrop"
                app:layout_collapseMode="parallax"
                app:layout_collapseParallaxMultiplier="0.4" />

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="@drawable/gradient_bg"
                android:orientation="vertical"
                app:layout_behavior="@string/appbar_scrolling_view_behavior"
                android:gravity="center_horizontal">
            </LinearLayout>
        </android.support.design.widget.CollapsingToolbarLayout>
    </android.support.design.widget.AppBarLayout>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        android:orientation="vertical">
        <android.support.design.widget.TabLayout
            android:id="@+id/circleresdyn_tablayout"
            style="@style/cirres_tablayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/main_color"/>
        <android.support.v4.view.ViewPager
            android:id="@+id/circleresdyn_viewpager"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
    </LinearLayout>
</android.support.design.widget.CoordinatorLayout></RelativeLayout>
Andy.Zhao
  • 250
  • 3
  • 16
  • Hi Andy, I wanted to have that nice animation coming from the Floating Action Button when the image hides. Also I see that the circleback image is match_parent, match_parent which I think, is not the case. :) Can you post a screenshot how it works? – NMP Sep 21 '15 at 06:00
-3

You can use toolbar to achieve what you want like this:

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

    <android.support.design.widget.AppBarLayout
        android:id="@+id/app_bar_layout"
        android:elevation="1dp"
        android:fitsSystemWindows="true"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

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

            <ImageView
                android:id="@+id/img"
                android:src="@drawable/header_bg"
                android:scaleType="centerCrop"
                android:cropToPadding="true"
                app:layout_collapseMode="parallax"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />
          <android.support.v7.widget.Toolbar
                    android:id="@+id/toolbar"
                    android:layout_width="match_parent"
                    android:layout_height="?attr/actionBarSize"
                    app:layout_collapseMode="pin"/>

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


    <android.support.v4.view.ViewPager
        android:id="@+id/profile_tabs"
        android:elevation="2dp"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />



          <android.support.design.widget.FloatingActionButton
               android:id="@+id/test"
               android:layout_width="wrap_content"
               android:layout_height="wrap_content"
               android:elevation="1dp"
               app:pressedTranslationZ="12dp"
               android:clickable="true"
               app:rippleColor="@android:color/transparent"
               android:src="@drawable/ic_launcher"
               app:layout_collapseMode="parallax"
               app:layout_anchor="@id/app_bar_layout"
               app:layout_anchorGravity="bottom|left|end" />

    </android.support.design.widget.CoordinatorLayout>

Without the toolbar the FloatingActionButton doesn't hide in the way you want.

Aakash
  • 5,181
  • 5
  • 20
  • 37
  • If you read carefully the question it's already stated that with the toolbar it works. – rciovati Sep 17 '15 at 14:53
  • Yes, it works with the toolbar. I want it to work without the toolbar. :) I think that the answer from Google says: If you want it, do it yourself... – NMP Sep 21 '15 at 05:41
-5

If I understood correctly your question (probably not), then try to create a scroll listener and hide it from there. If I'm not wrong, then it should be like this, but fix me if I'm wrong:

viewPager.setOnScrollListener(new OnScrollListener() {
    @Override
    public void onScroll(View v) {
        fab.setVisibility(View.GONE);
    }
}
Ido Naveh
  • 2,442
  • 3
  • 26
  • 57
  • 1
    You probably didn't get the point. The FAB is anchored to the AppBarLayout and should be hidden or shown accordingly, like in this video: http://goo.gl/8pDqZq – rciovati Sep 11 '15 at 08:40
  • I'm pretty sure that I've answered about that. On scrolling the FAB will be hidden – Ido Naveh Sep 12 '15 at 17:13
  • Read again the question... the problem is not just about hiding the FAB on scrolling. – rciovati Sep 12 '15 at 19:32
  • The scroll listener doesn't help. I tried implementing the scroll listener at the RecyclerView and manually hide the button but it doesn't work. The only solution is to have a toolbar. Even if you make the toolbar with height 1 dp it still doesn't work. It needs to be somewhere around 100 and something dps. Pretty weird, huh. – NMP Sep 21 '15 at 05:40