From 863aa3f3c2d7c85ae9346612812ab869ad54823a Mon Sep 17 00:00:00 2001 From: Aurelien Hubert Date: Wed, 20 Apr 2016 12:29:50 +0200 Subject: Fixed animations for Android pre KitKat Added an example with Vector Drawable --- ahbottomnavigation/build.gradle | 8 +- .../AHBottomNavigationBehavior.java | 106 ++++++++++++++++----- demo/build.gradle | 2 +- .../ahbottomnavigation/demo/DemoActivity.java | 2 +- demo/src/main/res/drawable/ic_apps_black_24dp.xml | 9 ++ 5 files changed, 99 insertions(+), 28 deletions(-) create mode 100644 demo/src/main/res/drawable/ic_apps_black_24dp.xml diff --git a/ahbottomnavigation/build.gradle b/ahbottomnavigation/build.gradle index 6b469d9..0d78d90 100644 --- a/ahbottomnavigation/build.gradle +++ b/ahbottomnavigation/build.gradle @@ -13,7 +13,7 @@ ext { siteUrl = 'https://github.com/aurelhubert/ahbottomnavigation' gitUrl = 'https://github.com/aurelhubert/ahbottomnavigation.git' - libraryVersion = '1.1.1' + libraryVersion = '1.1.2' developerId = 'aurelhubert' developerName = 'Aurelien Hubert' @@ -26,13 +26,13 @@ ext { android { compileSdkVersion 23 - buildToolsVersion "23.0.2" + buildToolsVersion "23.0.3" defaultConfig { minSdkVersion 14 targetSdkVersion 23 - versionCode 18 - versionName "1.1.1" + versionCode 19 + versionName "1.1.2" } buildTypes { release { diff --git a/ahbottomnavigation/src/main/java/com/aurelhubert/ahbottomnavigation/AHBottomNavigationBehavior.java b/ahbottomnavigation/src/main/java/com/aurelhubert/ahbottomnavigation/AHBottomNavigationBehavior.java index ab6755e..62515c3 100644 --- a/ahbottomnavigation/src/main/java/com/aurelhubert/ahbottomnavigation/AHBottomNavigationBehavior.java +++ b/ahbottomnavigation/src/main/java/com/aurelhubert/ahbottomnavigation/AHBottomNavigationBehavior.java @@ -1,5 +1,7 @@ package com.aurelhubert.ahbottomnavigation; +import android.animation.ObjectAnimator; +import android.animation.ValueAnimator; import android.content.Context; import android.content.res.TypedArray; import android.os.Build; @@ -12,6 +14,7 @@ import android.support.v4.view.ViewPropertyAnimatorCompat; import android.support.v4.view.ViewPropertyAnimatorUpdateListener; import android.support.v4.view.animation.LinearOutSlowInInterpolator; import android.util.AttributeSet; +import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.view.animation.Interpolator; @@ -26,7 +29,8 @@ public class AHBottomNavigationBehavior extends VerticalScrollin private int mTabLayoutId; private boolean hidden = false; - private ViewPropertyAnimatorCompat mTranslationAnimator; + private ViewPropertyAnimatorCompat translationAnimator; + private ObjectAnimator translationObjectAnimator; private TabLayout mTabLayout; private Snackbar.SnackbarLayout snackbarLayout; private FloatingActionButton floatingActionButton; @@ -102,16 +106,32 @@ public class AHBottomNavigationBehavior extends VerticalScrollin return true; } + /** + * Animate offset + * + * @param child + * @param offset + */ private void animateOffset(final V child, final int offset) { - ensureOrCancelAnimator(child); - mTranslationAnimator.translationY(offset).start(); + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { + ensureOrCancelObjectAnimation(child, offset); + translationObjectAnimator.start(); + } else { + ensureOrCancelAnimator(child); + translationAnimator.translationY(offset).start(); + } } + /** + * Manage animation for Android >= KITKAT + * + * @param child + */ private void ensureOrCancelAnimator(V child) { - if (mTranslationAnimator == null) { - mTranslationAnimator = ViewCompat.animate(child); - mTranslationAnimator.setDuration(ANIM_DURATION); - mTranslationAnimator.setUpdateListener(new ViewPropertyAnimatorUpdateListener() { + if (translationAnimator == null) { + translationAnimator = ViewCompat.animate(child); + translationAnimator.setDuration(ANIM_DURATION); + translationAnimator.setUpdateListener(new ViewPropertyAnimatorUpdateListener() { @Override public void onAnimationUpdate(View view) { // Animate snackbar @@ -130,12 +150,51 @@ public class AHBottomNavigationBehavior extends VerticalScrollin } } }); - mTranslationAnimator.setInterpolator(INTERPOLATOR); + translationAnimator.setInterpolator(INTERPOLATOR); } else { - mTranslationAnimator.cancel(); + translationAnimator.cancel(); } } + /** + * Manage animation for Android < KITKAT + * + * @param child + */ + private void ensureOrCancelObjectAnimation(final V child, final int offset) { + + if (translationObjectAnimator != null) { + Log.d("AHBottomNav", "ensureOrCancelObjectAnimation: CANCEL"); + translationObjectAnimator.cancel(); + } + Log.d("AHBottomNav", "ensureOrCancelObjectAnimation: NEW"); + translationObjectAnimator = ObjectAnimator.ofFloat(child, View.TRANSLATION_Y, offset); + translationObjectAnimator.setDuration(ANIM_DURATION); + translationObjectAnimator.setInterpolator(INTERPOLATOR); + translationObjectAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + if (snackbarLayout != null && snackbarLayout.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) { + targetOffset = child.getMeasuredHeight() - child.getTranslationY(); + ViewGroup.MarginLayoutParams p = (ViewGroup.MarginLayoutParams) snackbarLayout.getLayoutParams(); + p.setMargins(p.leftMargin, p.topMargin, p.rightMargin, (int) targetOffset); + snackbarLayout.requestLayout(); + } + // Animate Floating Action Button + if (floatingActionButton != null && floatingActionButton.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) { + ViewGroup.MarginLayoutParams p = (ViewGroup.MarginLayoutParams) floatingActionButton.getLayoutParams(); + fabTargetOffset = fabDefaultBottomMargin - child.getTranslationY() + snackBarY; + p.setMargins(p.leftMargin, p.topMargin, p.rightMargin, (int) fabTargetOffset); + floatingActionButton.requestLayout(); + + Log.d("AHBottomNav", "onLayoutChange: " + fabTargetOffset + " / " + + fabDefaultBottomMargin + " / " + child.getTranslationY() + " / " + + snackBarY); + } + } + }); + } + public static AHBottomNavigationBehavior from(V view) { ViewGroup.LayoutParams params = view.getLayoutParams(); @@ -167,19 +226,22 @@ public class AHBottomNavigationBehavior extends VerticalScrollin if (dependency != null && dependency instanceof Snackbar.SnackbarLayout) { snackbarLayout = (Snackbar.SnackbarLayout) dependency; - snackbarLayout.addOnLayoutChangeListener(new View.OnLayoutChangeListener() { - @Override - public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { - snackBarY = bottom - v.getY(); - if (floatingActionButton != null && - floatingActionButton.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) { - ViewGroup.MarginLayoutParams p = (ViewGroup.MarginLayoutParams) floatingActionButton.getLayoutParams(); - fabTargetOffset = fabDefaultBottomMargin - child.getTranslationY() + snackBarY; - p.setMargins(p.leftMargin, p.topMargin, p.rightMargin, (int) fabTargetOffset); - floatingActionButton.requestLayout(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + snackbarLayout.addOnLayoutChangeListener(new View.OnLayoutChangeListener() { + @Override + public void onLayoutChange(View v, int left, int top, int right, int bottom, + int oldLeft, int oldTop, int oldRight, int oldBottom) { + if (floatingActionButton != null && + floatingActionButton.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) { + ViewGroup.MarginLayoutParams p = (ViewGroup.MarginLayoutParams) floatingActionButton.getLayoutParams(); + snackBarY = bottom - v.getY(); + fabTargetOffset = fabDefaultBottomMargin - child.getTranslationY() + snackBarY; + p.setMargins(p.leftMargin, p.topMargin, p.rightMargin, (int) fabTargetOffset); + floatingActionButton.requestLayout(); + } } - } - }); + }); + } if (mSnackbarHeight == -1) { mSnackbarHeight = dependency.getHeight(); @@ -202,7 +264,7 @@ public class AHBottomNavigationBehavior extends VerticalScrollin * Update floating action button bottom margin */ public void updateFloatingActionButton(View dependency) { - if (dependency != null && dependency instanceof FloatingActionButton) { + if (dependency != null && dependency instanceof FloatingActionButton) { floatingActionButton = (FloatingActionButton) dependency; if (!fabBottomMarginInitialized && dependency.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) { fabBottomMarginInitialized = true; diff --git a/demo/build.gradle b/demo/build.gradle index 1c22e8e..219b1cd 100644 --- a/demo/build.gradle +++ b/demo/build.gradle @@ -2,7 +2,7 @@ apply plugin: 'com.android.application' android { compileSdkVersion 23 - buildToolsVersion "23.0.2" + buildToolsVersion "23.0.3" defaultConfig { applicationId "com.aurelhubert.ahbottomnavigation.demo" diff --git a/demo/src/main/java/com/aurelhubert/ahbottomnavigation/demo/DemoActivity.java b/demo/src/main/java/com/aurelhubert/ahbottomnavigation/demo/DemoActivity.java index a493cce..b277466 100644 --- a/demo/src/main/java/com/aurelhubert/ahbottomnavigation/demo/DemoActivity.java +++ b/demo/src/main/java/com/aurelhubert/ahbottomnavigation/demo/DemoActivity.java @@ -41,7 +41,7 @@ public class DemoActivity extends AppCompatActivity { bottomNavigation = (AHBottomNavigation) findViewById(R.id.bottom_navigation); floatingActionButton = (FloatingActionButton) findViewById(R.id.floating_action_button); - AHBottomNavigationItem item1 = new AHBottomNavigationItem(R.string.tab_1, R.drawable.ic_maps_place, R.color.color_tab_1); + AHBottomNavigationItem item1 = new AHBottomNavigationItem(R.string.tab_1, R.drawable.ic_apps_black_24dp, R.color.color_tab_1); AHBottomNavigationItem item2 = new AHBottomNavigationItem(R.string.tab_2, R.drawable.ic_maps_local_bar, R.color.color_tab_2); AHBottomNavigationItem item3 = new AHBottomNavigationItem(R.string.tab_3, R.drawable.ic_maps_local_restaurant, R.color.color_tab_3); diff --git a/demo/src/main/res/drawable/ic_apps_black_24dp.xml b/demo/src/main/res/drawable/ic_apps_black_24dp.xml new file mode 100644 index 0000000..ff485cf --- /dev/null +++ b/demo/src/main/res/drawable/ic_apps_black_24dp.xml @@ -0,0 +1,9 @@ + + + -- cgit v1.2.3