Search code examples
androidandroid-fragmentsandroid-viewpagerandroid-recyclerviewfloating-action-button

Floating Action Button in an Activity - how to anchor to a recyclerview in a fragment?


I had the same problem in this question Floating Action Button not showing fully inside a fragment

I have a tablayout in my activity_main and 2 tabs (with different fragments, one of them contains a recyclerView). When I put the FAB in the fragment,The FAB was not fully showed until I scrolled down the recyclerView.

So, I moved my FAB in the activity_main.xml file in the coordinator_layout widget as suggested in the linked question and it works good.

In this way I have a FAB in the activity and not in the fragment and I would like to know how to anchor, for example , my fab to the recyclerview in the fragment, for example for let it animate during the recycler scroll?

Now activity_main.xml with a tablayout :

activity_main.xml

<android.support.design.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.support.design.widget.AppBarLayout
        android:id="@+id/appbarlayout1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:fitsSystemWindows="true" >

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar1"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            app:layout_scrollFlags="scroll|enterAlways"
            android:background="?attr/colorPrimary" />

        <android.support.design.widget.TabLayout
            android:id="@+id/tabLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/toolbar1"
            android:background="?attr/colorPrimary"
            android:scrollbars="horizontal"
            app:tabMode="scrollable" />

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

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


    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:layout_gravity="bottom|right"
        android:layout_marginBottom="20dp"
        android:layout_marginRight="20dp"
        android:src="@drawable/ic_action_location_found"
        app:fabSize="normal" />
    </android.support.design.widget.CoordinatorLayout>

fragment.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="@dimen/activity_vertical_margin" >

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


</RelativeLayout>

Solution

  • Have you tried anchor it to the viewpager?

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        app:layout_anchor="@id/viewpager"
        app:layout_anchorGravity="bottom|right|end"
    </android.support.design.widget.CoordinatorLayout>
    

    Then you extend a FloatingActionButton.Behavior to repond to CoordinatorLayout events:

    public class ScrollAwareFABBehavior extends FloatingActionButton.Behavior {
    
        public ScrollAwareFABBehavior(Context context, AttributeSet attrs) {
             super();
        }
    
        @Override
        public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout,
                                       FloatingActionButton child, View directTargetChild, View target, int nestedScrollAxes) {
        return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL ||
                super.onStartNestedScroll(coordinatorLayout, child, directTargetChild, target,
                        nestedScrollAxes);
        }
    
        @Override
        public void onNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionButton child,
                               View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
        super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed,
                dyUnconsumed);
    
            if (dyConsumed > 0 && child.getVisibility() == View.VISIBLE) {
                child.hide();
             } else if (dyConsumed < 0 && child.getVisibility() != View.VISIBLE) {
                 child.show();
             }
         }
    
     }
    

    And add this to your FloatingButton:

    app:layout_behavior="com.package.yourapp.ScrollAwareFABBehavior"
    

    It's well explained here:

    https://guides.codepath.com/android/Floating-Action-Buttons