Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android Design Support Library FAB in a ViewPager Fragment with Coordinator Layout

I'm trying to get a Floating Action Button from the Android Design Support Library inside a Fragment which is inside a ViewPager. I've 4 tabs and I want the FAB in only one of the Tabs. My layout are as follows:

main_layout.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:id="@+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent">

<android.support.design.widget.AppBarLayout
    android:id="@+id/appbar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

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

    <android.support.design.widget.TabLayout
        android:id="@+id/tabs"
        app:tabIndicatorHeight="3dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</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" />

list_fragment_with_fab.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:padding="5dip"
android:background="@color/Transparent_White"
android:fitsSystemWindows="false"
android:layout_width="match_parent"
android:layout_height="match_parent">

<org.lucasr.twowayview.widget.TwoWayView
    android:id="@+id/clip_recycler_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:twowayview_layoutManager="ListLayoutManager" />

<android.support.design.widget.FloatingActionButton
    android:id="@+id/add_list_button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="bottom|right"
    android:layout_margin="16dp"
    android:src="@drawable/ic_list_add"
    app:layout_anchor="@+id/clip_recycler_view"
    app:layout_anchorGravity="bottom|right|end" />

Now the problem is, the FAB does not work as per the design specs. i.e the hiding and showing of the fab doesn't work. Also, the FAB is not at it's initial place when the fragment is activated. I've attached screenshots below to make it more clear.

The in the left image, as you can see, the FAB is off the screen. When I scroll, the Toolbar will hide (think Play Store App) and the tabs remain, that time the FAB will scroll up.

enter image description here

Is this a bug in the Design Support library? Or is my layout incorrect? Also, I want the FAB in only one of the fragments, so adding in the main_layout.xml kinda defeats that purpose.

like image 946
PsyGik Avatar asked Oct 06 '15 12:10

PsyGik


1 Answers

It's not strictly a bug, but just the way they've implemented it.

It's because of this:

app:layout_behavior="@string/appbar_scrolling_view_behavior"

This behavior doesn't manipulate the size of the ViewPager, it just pushes it off the bottom of the screen when the AppBarLayout is expanded.

Your fragment is filling the entire size of the ViewPager and so correctly aligns the FAB to the bottom right of the ViewPager container; but because the ViewPager container is offset, the bottom right is offscreen.

The "proper" way of using a FloatingActionButton in this context is by having the activity show it - 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"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main_content"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:context="bubblebearapps.co.uk.nfcapi.MainActivity">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingTop="@dimen/appbar_padding_top"
        android:theme="@style/AppTheme.AppBarOverlay">

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

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

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

    <android.support.v4.view.ViewPager
        android:id="@+id/container"
        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_gravity="end|bottom"
        android:layout_margin="@dimen/fab_margin"
        android:src="@android:drawable/ic_dialog_email" />

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

You then change the FloatingActionButton's size, icon and onClickBehaviour based on what page is shown in the ViewPager using the OnPageChangeListener interface.

To make the FloatingActionButton scroll off the bottom when you're scolling the RecyclerView, you must create a Behaviour! This is one I used in a different project:

public class ScrollOffBottomBehaviour extends CoordinatorLayout.Behavior<View> {

    private int mViewHeight;
    private ObjectAnimator mAnimator;

    public ScrollOffBottomBehaviour(Context context, AttributeSet attrs) {
        super();
    }

    @Override
    public boolean onLayoutChild(CoordinatorLayout parent, View child, int layoutDirection) {

        mViewHeight = child.getHeight();

        return super.onLayoutChild(parent, child, layoutDirection);
    }

    @Override
    public void onNestedScroll(CoordinatorLayout coordinatorLayout, View child,
            View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {


        if(mAnimator == null || !mAnimator.isRunning()){
            int totalScroll = (dyConsumed + dyUnconsumed);

            int targetTranslation = totalScroll > 0 ? mViewHeight : 0;

            mAnimator = ObjectAnimator.ofFloat(child, "translationY", targetTranslation);
            mAnimator.start();
        }
    }

    @Override
    public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, View child, View directTargetChild, View target, int nestedScrollAxes) {

        return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL;


    }


}

Set this onto your FloatingActionButton with app:layout_behaviour and all should be well...

like image 60
JoeyJubb Avatar answered Sep 24 '22 22:09

JoeyJubb