diff --git a/Habitica/res/anim/fab_slide_in.xml b/Habitica/res/anim/fab_slide_in.xml
new file mode 100644
index 000000000..1675a9ae1
--- /dev/null
+++ b/Habitica/res/anim/fab_slide_in.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/Habitica/res/anim/fab_slide_out.xml b/Habitica/res/anim/fab_slide_out.xml
new file mode 100644
index 000000000..b82f4d744
--- /dev/null
+++ b/Habitica/res/anim/fab_slide_out.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/Habitica/src/com/habitrpg/android/habitica/ui/helpers/FloatingActionMenuBehavior.java b/Habitica/src/com/habitrpg/android/habitica/ui/helpers/FloatingActionMenuBehavior.java
index 2e4eb2b32..afc0bcadf 100644
--- a/Habitica/src/com/habitrpg/android/habitica/ui/helpers/FloatingActionMenuBehavior.java
+++ b/Habitica/src/com/habitrpg/android/habitica/ui/helpers/FloatingActionMenuBehavior.java
@@ -9,16 +9,29 @@ import android.support.v4.view.ViewCompat;
import android.support.v4.view.ViewPropertyAnimatorListener;
import android.util.AttributeSet;
import android.view.View;
+import android.view.animation.Animation;
+import android.view.animation.AnimationUtils;
import com.github.clans.fab.FloatingActionMenu;
+import com.habitrpg.android.habitica.R;
import java.util.List;
public class FloatingActionMenuBehavior extends CoordinatorLayout.Behavior {
+
+ private final int FAB_ANIMATION_DURATION = 500;
+
private float mTranslationY;
+ private Context context;
+ private boolean isAnimating;
+ private boolean isOffScreen;
+
public FloatingActionMenuBehavior(Context context, AttributeSet attrs) {
super();
+ this.context = context;
+ isAnimating = false;
+ isOffScreen = false;
}
@Override
@@ -75,13 +88,53 @@ public class FloatingActionMenuBehavior extends CoordinatorLayout.Behavior {
}
@Override
- public void onNestedScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
+ public void onNestedScroll(CoordinatorLayout coordinatorLayout, final View child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed);
- if (dyConsumed > 20 && child.getVisibility() == View.VISIBLE) {
- child.setVisibility(View.INVISIBLE);
- } else if (dyConsumed < -20 && child.getVisibility() != View.VISIBLE) {
- child.setVisibility(View.VISIBLE);
+ /*
+ Logic:
+ - If we're scrolling downwards or we're at the bottom of the screen
+ AND if we're not animating and not on screen > HIDE
+ */
+ if ((dyConsumed > 20 || (dyConsumed == 0 && dyUnconsumed > 0)) && !isAnimating && !isOffScreen) {
+ isAnimating = true;
+ slideFabOffScreen(child);
+ resetAnimatingStatusWithDelay(child);
+ isOffScreen = true;
+
+ /*
+ Logic:
+ - If we're not on screen
+ AND we're scrolling upwards and not animating OR we're at the top of the screen > SHOW
+ */
+ } else if (isOffScreen && ((dyConsumed < -10 && !isAnimating) || dyUnconsumed < 0)) {
+ isAnimating = true;
+ slideFabOnScreen(child);
+ resetAnimatingStatusWithDelay(child);
+ isOffScreen = false;
}
}
+
+ private void resetAnimatingStatusWithDelay(View child) {
+ child.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ isAnimating = false;
+ }
+ }, FAB_ANIMATION_DURATION);
+ }
+
+ private void slideFabOffScreen(View view){
+ Animation slideOff = AnimationUtils.loadAnimation(context, R.anim.fab_slide_out);
+ slideOff.setDuration(FAB_ANIMATION_DURATION);
+ slideOff.setFillAfter(true);
+ view.startAnimation(slideOff);
+ }
+
+ private void slideFabOnScreen(View view){
+ Animation slideIn = AnimationUtils.loadAnimation(context, R.anim.fab_slide_in);
+ slideIn.setDuration(FAB_ANIMATION_DURATION);
+ slideIn.setFillAfter(true);
+ view.startAnimation(slideIn);
+ }
}
\ No newline at end of file