Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add FAB layout behavior: hide/show animation durning scrolling event #19

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,13 @@ android {

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])

compile "com.android.support:appcompat-v7:22.+"
compile 'com.android.support:appcompat-v7:22.+'
compile 'com.android.support:support-v13:22.+'
compile 'com.android.support:support-v4:22.+'
compile 'com.android.support:palette-v7:22.+'
compile 'com.android.support:recyclerview-v7:22.+'
compile 'com.android.support:cardview-v7:22.+'
compile 'com.android.support:design:22.2.1'

compile 'com.jakewharton:butterknife:6.1.0'
compile 'com.jakewharton.timber:timber:2.5.1'
compile 'com.facebook.rebound:rebound:0.3.6'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
package io.github.froger.instamaterial.ui.behavior;

import android.content.Context;
import android.os.Build;
import android.support.design.widget.CoordinatorLayout;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.view.ViewCompat;
import android.support.v4.view.ViewPropertyAnimatorListener;
import android.support.v4.view.animation.FastOutSlowInInterpolator;

import android.support.v4.view.animation.LinearOutSlowInInterpolator;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.animation.AnticipateInterpolator;
import android.view.animation.Interpolator;

import io.github.froger.instamaterial.R;

/**
* Created by moses on 8/6/15.
*/
public class ScrollAwareFABBehavior extends FloatingActionButton.Behavior {
private static final Interpolator INTERPOLATOR = new FastOutSlowInInterpolator();
private boolean mIsAnimatingOut = false;

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

@Override
public boolean onStartNestedScroll(final CoordinatorLayout coordinatorLayout,
final FloatingActionButton child,
final View directTargetChild,
final View target, final int nestedScrollAxes) {
// Ensure we react to vertical scrolling
return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL
|| super.onStartNestedScroll(coordinatorLayout,
child, directTargetChild, target, nestedScrollAxes);
}

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

super.onNestedScroll(coordinatorLayout, child, target,
dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed);

if (dyConsumed > 0 && !this.mIsAnimatingOut && child.getVisibility() == View.VISIBLE) {
// User scrolled down and the FAB is currently visible -> hide the FAB
animateOut(child);
} else if (dyConsumed < 0 && child.getVisibility() != View.VISIBLE) {
// User scrolled up and the FAB is currently not visible -> show the FAB
animateIn(child);
}
}

// Same animation that FloatingActionButton.Behavior uses to hide the FAB when the AppBarLayout exits
private void animateOut(final FloatingActionButton button) {
CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams) button.getLayoutParams();
int fabBottom = lp.bottomMargin;

if (Build.VERSION.SDK_INT >= 14) {
ViewCompat.animate(button).setDuration(300L)
.translationY(button.getHeight() + fabBottom)
.setInterpolator(INTERPOLATOR)
.setListener(new ViewPropertyAnimatorListener() {
public void onAnimationStart(View view) {
ScrollAwareFABBehavior.this.mIsAnimatingOut = true;
}

public void onAnimationCancel(View view) {
ScrollAwareFABBehavior.this.mIsAnimatingOut = false;
}

public void onAnimationEnd(View view) {
ScrollAwareFABBehavior.this.mIsAnimatingOut = false;
view.setVisibility(View.GONE);
}
}).start();
} else {
Animation anim = AnimationUtils.loadAnimation(button.getContext(), R.anim.fab_out);
anim.setInterpolator(INTERPOLATOR);
anim.setDuration(300L);
anim.setAnimationListener(new Animation.AnimationListener() {
public void onAnimationStart(Animation animation) {
ScrollAwareFABBehavior.this.mIsAnimatingOut = true;
}

public void onAnimationEnd(Animation animation) {
ScrollAwareFABBehavior.this.mIsAnimatingOut = false;
button.setVisibility(View.GONE);
}

@Override
public void onAnimationRepeat(final Animation animation) {
}
});
button.startAnimation(anim);
}
}

// Same animation that FloatingActionButton.Behavior uses to show the FAB when the AppBarLayout enters
private void animateIn(FloatingActionButton button) {

button.setVisibility(View.VISIBLE);
if (Build.VERSION.SDK_INT >= 14) {
ViewCompat.animate(button).setDuration(300L).translationY(0.0F)
.scaleX(1.0F).scaleY(1.0F).alpha(1.0F)
.setInterpolator(INTERPOLATOR).withLayer().setListener(null)
.start();
} else {
Animation anim = AnimationUtils.loadAnimation(button.getContext(), R.anim.fab_in);
anim.setDuration(300L);
anim.setInterpolator(INTERPOLATOR);
button.startAnimation(anim);
}
}
}
16 changes: 6 additions & 10 deletions app/src/main/res/layout/activity_drawer.xml
Original file line number Diff line number Diff line change
@@ -1,21 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="vertical">

<android.support.v4.widget.DrawerLayout
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/drawerLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">

<FrameLayout
<FrameLayout
android:id="@+id/flContentRoot"
android:layout_width="match_parent"
android:layout_height="match_parent" />

<android.support.design.widget.NavigationView
<android.support.design.widget.NavigationView
android:id="@+id/vNavigation"
android:layout_width="wrap_content"
android:layout_height="match_parent"
Expand All @@ -26,5 +23,4 @@
app:itemTextColor="#666666"
app:menu="@menu/drawer_menu" />

</android.support.v4.widget.DrawerLayout>
</LinearLayout>
</android.support.v4.widget.DrawerLayout>
33 changes: 15 additions & 18 deletions app/src/main/res/layout/activity_main.xml
Original file line number Diff line number Diff line change
@@ -1,35 +1,32 @@
<RelativeLayout 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/root"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

<android.support.design.widget.CoordinatorLayout
<?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/content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
android:orientation="vertical"
tools:context=".MainActivity">

<android.support.v7.widget.RecyclerView
<android.support.v7.widget.RecyclerView
android:id="@+id/rvFeed"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="none"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />

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

<include
<include
android:id="@+id/toolbar"
layout="@layout/view_feed_toolbar" />
</android.support.design.widget.AppBarLayout>
</android.support.design.widget.AppBarLayout>

<android.support.design.widget.FloatingActionButton
<android.support.design.widget.FloatingActionButton
android:id="@+id/btnCreate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
Expand All @@ -39,8 +36,8 @@
android:src="@drawable/ic_instagram_white"
app:borderWidth="0dp"
app:elevation="6dp"
app:pressedTranslationZ="12dp" />
app:pressedTranslationZ="12dp"
app:layout_behavior="io.github.froger.instamaterial.ui.behavior.ScrollAwareFABBehavior"/>

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

</RelativeLayout>