Merge "Support design - fix FloatingActionButton elevation"
diff --git a/design/lollipop/android/support/design/widget/FloatingActionButtonLollipop.java b/design/lollipop/android/support/design/widget/FloatingActionButtonLollipop.java
index 1d62c67..c61dc2a 100644
--- a/design/lollipop/android/support/design/widget/FloatingActionButtonLollipop.java
+++ b/design/lollipop/android/support/design/widget/FloatingActionButtonLollipop.java
@@ -100,14 +100,17 @@
 
         // Animate translationZ to 0 if not pressed
         set = new AnimatorSet();
-        // Use an AnimatorSet to set a start delay since there is a bug with ValueAnimator that
-        // prevents it from being cancelled properly when used with a StateListAnimator.
-        AnimatorSet anim = new AnimatorSet();
-        anim.play(ObjectAnimator.ofFloat(mView, View.TRANSLATION_Z, 0f)
-                        .setDuration(PRESSED_ANIM_DURATION))
-                .after(PRESSED_ANIM_DURATION);
-        set.play(ObjectAnimator.ofFloat(mView, "elevation", elevation).setDuration(0))
-                .with(anim);
+        set.playSequentially(
+                ObjectAnimator.ofFloat(mView, "elevation", elevation).setDuration(0),
+                // This is a no-op animation which exists here only for introducing the duration
+                // because setting the delay (on the next animation) via "setDelay" or "after" can
+                // trigger a NPE between android versions 21 and 24 (due to a framework bug). The
+                // issue has been fixed in version 25.
+                ObjectAnimator.ofFloat(mView, View.TRANSLATION_Z, mView.getTranslationZ())
+                        .setDuration(PRESSED_ANIM_DELAY),
+                ObjectAnimator.ofFloat(mView, View.TRANSLATION_Z, 0f)
+                        .setDuration(PRESSED_ANIM_DURATION));
+
         set.setInterpolator(ANIM_INTERPOLATOR);
         stateListAnimator.addState(ENABLED_STATE_SET, set);
 
diff --git a/design/tests/src/android/support/design/testutils/FloatingActionButtonActions.java b/design/tests/src/android/support/design/testutils/FloatingActionButtonActions.java
index 59b0d48..2716165 100644
--- a/design/tests/src/android/support/design/testutils/FloatingActionButtonActions.java
+++ b/design/tests/src/android/support/design/testutils/FloatingActionButtonActions.java
@@ -103,6 +103,30 @@
         };
     }
 
+    public static ViewAction setCompatElevation(final float size) {
+        return new ViewAction() {
+            @Override
+            public Matcher<View> getConstraints() {
+                return isAssignableFrom(FloatingActionButton.class);
+            }
+
+            @Override
+            public String getDescription() {
+                return "Sets FloatingActionButton elevation";
+            }
+
+            @Override
+            public void perform(UiController uiController, View view) {
+                uiController.loopMainThreadUntilIdle();
+
+                final FloatingActionButton fab = (FloatingActionButton) view;
+                fab.setCompatElevation(size);
+
+                uiController.loopMainThreadUntilIdle();
+            }
+        };
+    }
+
     public static ViewAction setLayoutGravity(final int gravity) {
         return new ViewAction() {
             @Override
diff --git a/design/tests/src/android/support/design/widget/FloatingActionButtonTest.java b/design/tests/src/android/support/design/widget/FloatingActionButtonTest.java
index 857121e..248b9df 100644
--- a/design/tests/src/android/support/design/widget/FloatingActionButtonTest.java
+++ b/design/tests/src/android/support/design/widget/FloatingActionButtonTest.java
@@ -18,10 +18,12 @@
 
 import static android.support.design.testutils.FloatingActionButtonActions.hideThenShow;
 import static android.support.design.testutils.FloatingActionButtonActions.setBackgroundTintColor;
+import static android.support.design.testutils.FloatingActionButtonActions.setCompatElevation;
 import static android.support.design.testutils.FloatingActionButtonActions.setImageResource;
 import static android.support.design.testutils.FloatingActionButtonActions.setLayoutGravity;
 import static android.support.design.testutils.FloatingActionButtonActions.setSize;
 import static android.support.design.testutils.FloatingActionButtonActions.showThenHide;
+import static android.support.design.testutils.TestUtilsActions.setEnabled;
 import static android.support.design.testutils.TestUtilsMatchers.withFabBackgroundFill;
 import static android.support.design.testutils.TestUtilsMatchers.withFabContentAreaOnMargins;
 import static android.support.design.testutils.TestUtilsMatchers.withFabContentHeight;
@@ -137,4 +139,14 @@
                 .check(matches(not(isDisplayed())));
     }
 
+    @Test
+    public void testSetCompatElevation() {
+        onView(withId(R.id.fab_standard))
+                .perform(setEnabled(false))
+                .perform(setCompatElevation(0));
+
+        onView(withId(R.id.fab_standard))
+                .perform(setEnabled(true))
+                .perform(setCompatElevation(8));
+    }
 }