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.
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.
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...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With