5555import androidx .core .view .ViewCompat .ScrollAxis ;
5656import androidx .core .view .WindowInsetsCompat ;
5757import androidx .customview .view .AbsSavedState ;
58+ import com .google .android .material .animation .AnimationUtils ;
5859import com .google .android .material .animation .TransformationCallback ;
5960import com .google .android .material .behavior .HideBottomViewOnScrollBehavior ;
6061import com .google .android .material .floatingactionbutton .ExtendedFloatingActionButton ;
6364import com .google .android .material .internal .ThemeEnforcement ;
6465import com .google .android .material .internal .ViewUtils ;
6566import com .google .android .material .internal .ViewUtils .RelativePadding ;
67+ import com .google .android .material .motion .MotionUtils ;
6668import com .google .android .material .resources .MaterialResources ;
6769import com .google .android .material .shape .EdgeTreatment ;
6870import com .google .android .material .shape .MaterialShapeDrawable ;
@@ -112,7 +114,11 @@ public class BottomAppBar extends Toolbar implements AttachedBehavior {
112114
113115 private static final int DEF_STYLE_RES = R .style .Widget_MaterialComponents_BottomAppBar ;
114116
115- private static final long ANIMATION_DURATION = 300 ;
117+ private static final int FAB_ALIGNMENT_ANIM_DURATION_DEFAULT = 300 ;
118+ private static final int FAB_ALIGNMENT_ANIM_DURATION_ATTR = R .attr .motionDurationLong2 ;
119+ private static final int FAB_ALIGNMENT_ANIM_EASING_ATTR =
120+ R .attr .motionEasingEmphasizedInterpolator ;
121+ private static final float FAB_ALIGNMENT_ANIM_EASING_MIDPOINT = .2F ;
116122
117123 public static final int FAB_ALIGNMENT_MODE_CENTER = 0 ;
118124 public static final int FAB_ALIGNMENT_MODE_END = 1 ;
@@ -503,10 +509,9 @@ public void performHide() {
503509 }
504510
505511 /**
506- * Hides the {@link BottomAppBar}.
512+ * Hides the {@link BottomAppBar}.
507513 *
508- * @param animate {@code false} to hide the {@link BottomAppBar} immediately
509- * without animation.
514+ * @param animate {@code false} to hide the {@link BottomAppBar} immediately without animation.
510515 */
511516 public void performHide (boolean animate ) {
512517 getBehavior ().slideDown (this , animate );
@@ -520,8 +525,7 @@ public void performShow() {
520525 /**
521526 * Shows the {@link BottomAppBar}.
522527 *
523- * @param animate {@code false} to show the {@link BottomAppBar} immediately without
524- * animation.
528+ * @param animate {@code false} to show the {@link BottomAppBar} immediately without animation.
525529 */
526530 public void performShow (boolean animate ) {
527531 getBehavior ().slideUp (this , animate );
@@ -633,6 +637,9 @@ private void maybeAnimateModeChange(@FabAlignmentMode int targetMode) {
633637
634638 AnimatorSet set = new AnimatorSet ();
635639 set .playTogether (animators );
640+ set .setInterpolator (
641+ MotionUtils .resolveThemeInterpolator (
642+ getContext (), FAB_ALIGNMENT_ANIM_EASING_ATTR , AnimationUtils .LINEAR_INTERPOLATOR ));
636643 modeAnimator = set ;
637644 modeAnimator .addListener (
638645 new AnimatorListenerAdapter () {
@@ -715,10 +722,15 @@ private void createFabTranslationXAnimation(
715722 @ FabAlignmentMode int targetMode , @ NonNull List <Animator > animators ) {
716723 ObjectAnimator animator =
717724 ObjectAnimator .ofFloat (findDependentFab (), "translationX" , getFabTranslationX (targetMode ));
718- animator .setDuration (ANIMATION_DURATION );
725+ animator .setDuration (getFabAlignmentAnimationDuration () );
719726 animators .add (animator );
720727 }
721728
729+ private int getFabAlignmentAnimationDuration () {
730+ return MotionUtils .resolveThemeDuration (
731+ getContext (), FAB_ALIGNMENT_ANIM_DURATION_ATTR , FAB_ALIGNMENT_ANIM_DURATION_DEFAULT );
732+ }
733+
722734 @ Nullable
723735 private Drawable maybeTintNavigationIcon (@ Nullable Drawable navigationIcon ) {
724736 if (navigationIcon != null && navigationIconTint != null ) {
@@ -785,7 +797,9 @@ private void createMenuViewTranslationAnimation(
785797 return ;
786798 }
787799
800+ final float animationDuration = getFabAlignmentAnimationDuration ();
788801 Animator fadeIn = ObjectAnimator .ofFloat (actionMenuView , "alpha" , 1 );
802+ fadeIn .setDuration ((long ) (animationDuration * (1F - FAB_ALIGNMENT_ANIM_EASING_MIDPOINT )));
789803
790804 float translationXDifference =
791805 actionMenuView .getTranslationX ()
@@ -795,6 +809,7 @@ private void createMenuViewTranslationAnimation(
795809 if (Math .abs (translationXDifference ) > 1 ) {
796810 // We need to fade the MenuView out and in because it's position is changing
797811 Animator fadeOut = ObjectAnimator .ofFloat (actionMenuView , "alpha" , 0 );
812+ fadeOut .setDuration ((long ) (animationDuration * FAB_ALIGNMENT_ANIM_EASING_MIDPOINT ));
798813
799814 fadeOut .addListener (
800815 new AnimatorListenerAdapter () {
@@ -816,7 +831,6 @@ public void onAnimationEnd(Animator animation) {
816831 });
817832
818833 AnimatorSet set = new AnimatorSet ();
819- set .setDuration (ANIMATION_DURATION / 2 );
820834 set .playSequentially (fadeOut , fadeIn );
821835 animators .add (set );
822836 } else if (actionMenuView .getAlpha () < 1 ) {
@@ -879,13 +893,14 @@ private void translateActionMenuView(
879893 @ FabAlignmentMode final int fabAlignmentMode ,
880894 final boolean fabAttached ,
881895 boolean shouldWaitForMenuReplacement ) {
882- Runnable runnable = new Runnable () {
883- @ Override
884- public void run () {
885- actionMenuView .setTranslationX (
886- getActionMenuViewTranslationX (actionMenuView , fabAlignmentMode , fabAttached ));
887- }
888- };
896+ Runnable runnable =
897+ new Runnable () {
898+ @ Override
899+ public void run () {
900+ actionMenuView .setTranslationX (
901+ getActionMenuViewTranslationX (actionMenuView , fabAlignmentMode , fabAttached ));
902+ }
903+ };
889904 if (shouldWaitForMenuReplacement ) {
890905 // Wait to ensure the actionMenuView has had it's menu inflated and is able to correctly
891906 // measure it's width before calculating and translating X.
@@ -1103,8 +1118,10 @@ public void onLayoutChange(
11031118 child .setFabDiameter (height );
11041119
11051120 // Assume symmetrical corners
1106- float cornerSize = fab .getShapeAppearanceModel ().getTopLeftCornerSize ()
1107- .getCornerSize (new RectF (fabContentRect ));
1121+ float cornerSize =
1122+ fab .getShapeAppearanceModel ()
1123+ .getTopLeftCornerSize ()
1124+ .getCornerSize (new RectF (fabContentRect ));
11081125
11091126 child .setFabCornerSize (cornerSize );
11101127
0 commit comments