Index: chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java |
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java |
index 8f4e4426c7cc8fe73e065d5eb313ad04adb01a33..ede7e626e835e6cc31653b71692edf5e9def8100 100644 |
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java |
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java |
@@ -6,6 +6,7 @@ package org.chromium.chrome.browser.widget.bottomsheet; |
import android.animation.Animator; |
import android.animation.AnimatorListenerAdapter; |
+import android.animation.AnimatorSet; |
import android.animation.ObjectAnimator; |
import android.animation.ValueAnimator; |
import android.content.Context; |
@@ -20,6 +21,7 @@ import android.view.GestureDetector; |
import android.view.MotionEvent; |
import android.view.VelocityTracker; |
import android.view.View; |
+import android.view.ViewGroup; |
import android.view.Window; |
import android.view.animation.DecelerateInterpolator; |
import android.view.animation.Interpolator; |
@@ -49,6 +51,8 @@ import org.chromium.content_public.browser.LoadUrlParams; |
import java.lang.annotation.Retention; |
import java.lang.annotation.RetentionPolicy; |
+import java.util.ArrayList; |
+import java.util.List; |
/** |
* This class defines the bottom sheet that has multiple states and a persistently showing toolbar. |
@@ -86,6 +90,9 @@ public class BottomSheet |
*/ |
private static final long BASE_ANIMATION_DURATION_MS = 218; |
+ /** The amount of time it takes to transition sheet content in or out. */ |
+ private static final long TRANSITION_DURATION_MS = 150; |
+ |
/** |
* The fraction of the way to the next state the sheet must be swiped to animate there when |
* released. This is the value used when there are 3 active states. A smaller value here means |
@@ -140,8 +147,8 @@ public class BottomSheet |
/** The animator used to move the sheet to a fixed state when released by the user. */ |
private ValueAnimator mSettleAnimator; |
- /** The animator used for the toolbar fades. */ |
- private ValueAnimator mToolbarFadeAnimator; |
+ /** The animator set responsible for swapping the bottom sheet content. */ |
+ private AnimatorSet mContentSwapAnimatorSet; |
/** The height of the toolbar. */ |
private float mToolbarHeight; |
@@ -557,7 +564,7 @@ public class BottomSheet |
LayoutParams placeHolderParams = |
new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); |
mPlaceholder.setBackgroundColor( |
- ApiCompatibilityUtils.getColor(getResources(), android.R.color.white)); |
+ ApiCompatibilityUtils.getColor(getResources(), R.color.default_primary_color)); |
mBottomSheetContentContainer.addView(mPlaceholder, placeHolderParams); |
mToolbarHolder = (FrameLayout) mControlContainer.findViewById(R.id.toolbar_holder); |
@@ -645,83 +652,89 @@ public class BottomSheet |
* Show content in the bottom sheet's content area. |
* @param content The {@link BottomSheetContent} to show. |
*/ |
- public void showContent(BottomSheetContent content) { |
+ public void showContent(final BottomSheetContent content) { |
// If the desired content is already showing, do nothing. |
if (mSheetContent == content) return; |
- View newToolbar = content.getToolbarView(); |
- View oldToolbar = null; |
- |
- if (mSheetContent != null) { |
- oldToolbar = mSheetContent.getToolbarView(); |
- mBottomSheetContentContainer.removeView(mSheetContent.getContentView()); |
- mSheetContent = null; |
- } |
- |
mBottomSheetContentContainer.removeView(mPlaceholder); |
- mSheetContent = content; |
- mBottomSheetContentContainer.addView(mSheetContent.getContentView()); |
- doToolbarSwap(newToolbar, oldToolbar); |
+ View newToolbar = |
+ content.getToolbarView() != null ? content.getToolbarView() : mDefaultToolbarView; |
+ View oldToolbar = mSheetContent != null && mSheetContent.getToolbarView() != null |
+ ? mSheetContent.getToolbarView() |
+ : mDefaultToolbarView; |
+ View oldContent = mSheetContent != null ? mSheetContent.getContentView() : null; |
- for (BottomSheetObserver o : mObservers) { |
- o.onSheetContentChanged(mSheetContent); |
- } |
- } |
+ // If an animation is already running, end it. |
+ if (mContentSwapAnimatorSet != null) mContentSwapAnimatorSet.end(); |
- /** |
- * Fade between a new toolbar and the old toolbar to be shown. A null parameter can be used to |
- * refer to the default omnibox toolbar. Normally, the new toolbar is attached to the toolbar |
- * container and faded in. In the case of the default toolbar, the old toolbar is faded out. |
- * This is because the default toolbar is always attached to the view hierarchy and sits behind |
- * the attach point for the other toolbars. |
- * @param newToolbar The toolbar that will be shown. |
- * @param oldToolbar The toolbar being replaced. |
- */ |
- private void doToolbarSwap(View newToolbar, View oldToolbar) { |
- if (mToolbarFadeAnimator != null) mToolbarFadeAnimator.end(); |
- |
- final View targetToolbar = newToolbar != null ? newToolbar : mDefaultToolbarView; |
- final View currentToolbar = oldToolbar != null ? oldToolbar : mDefaultToolbarView; |
- |
- if (targetToolbar == currentToolbar) return; |
- |
- if (targetToolbar != mDefaultToolbarView) { |
- mToolbarHolder.addView(targetToolbar); |
- targetToolbar.setAlpha(0f); |
- } else { |
- targetToolbar.setVisibility(View.VISIBLE); |
- targetToolbar.setAlpha(1f); |
- } |
- |
- mToolbarFadeAnimator = ObjectAnimator.ofFloat(0, 1); |
- mToolbarFadeAnimator.setDuration(BASE_ANIMATION_DURATION_MS); |
- mToolbarFadeAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { |
- @Override |
- public void onAnimationUpdate(ValueAnimator animator) { |
- if (targetToolbar == mDefaultToolbarView) { |
- currentToolbar.setAlpha(1f - animator.getAnimatedFraction()); |
- } else { |
- targetToolbar.setAlpha(animator.getAnimatedFraction()); |
- } |
- } |
- }); |
- mToolbarFadeAnimator.addListener(new AnimatorListenerAdapter() { |
+ List<Animator> animators = new ArrayList<>(); |
+ mContentSwapAnimatorSet = new AnimatorSet(); |
+ mContentSwapAnimatorSet.addListener(new AnimatorListenerAdapter() { |
@Override |
public void onAnimationEnd(Animator animation) { |
- targetToolbar.setAlpha(1f); |
- currentToolbar.setAlpha(0f); |
- if (currentToolbar != mDefaultToolbarView) { |
- mToolbarHolder.removeView(currentToolbar); |
- } else { |
- currentToolbar.setVisibility(View.GONE); |
+ mSheetContent = content; |
+ for (BottomSheetObserver o : mObservers) { |
+ o.onSheetContentChanged(content); |
} |
- mToolbarFadeAnimator = null; |
updateHandleTint(); |
+ mContentSwapAnimatorSet = null; |
} |
}); |
- mToolbarFadeAnimator.start(); |
+ // For the toolbar transition, make sure we don't detach the default toolbar view. |
+ animators.add(getViewTransitionAnimator( |
+ newToolbar, oldToolbar, mToolbarHolder, mDefaultToolbarView != oldToolbar)); |
+ animators.add(getViewTransitionAnimator( |
+ content.getContentView(), oldContent, mBottomSheetContentContainer, true)); |
+ |
+ mContentSwapAnimatorSet.playTogether(animators); |
+ mContentSwapAnimatorSet.start(); |
+ |
+ // If the existing content is null, end the animation immediately. |
+ if (mSheetContent == null) mContentSwapAnimatorSet.end(); |
+ } |
+ |
+ /** |
+ * Creates a transition animation between two views. The old view is faded out completely |
+ * before the new view is faded in. There is an option to detach the old view or not. |
+ * @param newView The new view to transition to. |
+ * @param oldView The old view to transition from. |
+ * @param detachOldView Whether or not to detach the old view once faded out. |
+ * @return An animator that runs the specified animation. |
+ */ |
+ private Animator getViewTransitionAnimator(final View newView, final View oldView, |
+ final ViewGroup parent, final boolean detachOldView) { |
+ if (newView == oldView) return null; |
+ |
+ AnimatorSet animatorSet = new AnimatorSet(); |
+ List<Animator> animators = new ArrayList<>(); |
+ |
+ // Fade out the old view. |
+ if (oldView != null) { |
+ ValueAnimator fadeOutAnimator = ObjectAnimator.ofFloat(oldView, View.ALPHA, 0); |
+ fadeOutAnimator.setDuration(TRANSITION_DURATION_MS); |
+ fadeOutAnimator.addListener(new AnimatorListenerAdapter() { |
+ @Override |
+ public void onAnimationEnd(Animator animation) { |
+ if (detachOldView && oldView.getParent() != null) { |
+ parent.removeView(oldView); |
+ } |
+ } |
+ }); |
+ animators.add(fadeOutAnimator); |
+ } |
+ |
+ // Fade in the new view. |
+ if (parent != newView.getParent()) parent.addView(newView); |
+ newView.setAlpha(0); |
+ ValueAnimator fadeInAnimator = ObjectAnimator.ofFloat(newView, View.ALPHA, 1); |
+ fadeInAnimator.setDuration(TRANSITION_DURATION_MS); |
+ animators.add(fadeInAnimator); |
+ |
+ animatorSet.playSequentially(animators); |
+ |
+ return animatorSet; |
} |
/** |