Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(82)

Side by Side Diff: chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java

Issue 2759823002: 🏠 Separate bottom sheet current from target state (Closed)
Patch Set: rebase Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 package org.chromium.chrome.browser.widget.bottomsheet; 5 package org.chromium.chrome.browser.widget.bottomsheet;
6 6
7 import android.animation.Animator; 7 import android.animation.Animator;
8 import android.animation.AnimatorListenerAdapter; 8 import android.animation.AnimatorListenerAdapter;
9 import android.animation.ValueAnimator; 9 import android.animation.ValueAnimator;
10 import android.content.Context; 10 import android.content.Context;
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
46 * - HALF: The sheet is expanded to consume around half of the screen. 46 * - HALF: The sheet is expanded to consume around half of the screen.
47 * - FULL: The sheet is expanded to its full height. 47 * - FULL: The sheet is expanded to its full height.
48 * 48 *
49 * All the computation in this file is based off of the bottom of the screen ins tead of the top 49 * All the computation in this file is based off of the bottom of the screen ins tead of the top
50 * for simplicity. This means that the bottom of the screen is 0 on the Y axis. 50 * for simplicity. This means that the bottom of the screen is 0 on the Y axis.
51 */ 51 */
52 52
53 public class BottomSheet 53 public class BottomSheet
54 extends FrameLayout implements FadingBackgroundView.FadingViewObserver, NativePageHost { 54 extends FrameLayout implements FadingBackgroundView.FadingViewObserver, NativePageHost {
55 /** The different states that the bottom sheet can have. */ 55 /** The different states that the bottom sheet can have. */
56 @IntDef({SHEET_STATE_PEEK, SHEET_STATE_HALF, SHEET_STATE_FULL}) 56 @IntDef({SHEET_STATE_PEEK, SHEET_STATE_HALF, SHEET_STATE_FULL, SHEET_STATE_S CROLLING})
57 @Retention(RetentionPolicy.SOURCE) 57 @Retention(RetentionPolicy.SOURCE)
58 public @interface SheetState {} 58 public @interface SheetState {}
59 public static final int SHEET_STATE_PEEK = 0; 59 public static final int SHEET_STATE_PEEK = 0;
60 public static final int SHEET_STATE_HALF = 1; 60 public static final int SHEET_STATE_HALF = 1;
61 public static final int SHEET_STATE_FULL = 2; 61 public static final int SHEET_STATE_FULL = 2;
62 public static final int SHEET_STATE_SCROLLING = 3;
62 63
63 /** 64 /**
64 * The base duration of the settling animation of the sheet. 218 ms is a spe c for material 65 * The base duration of the settling animation of the sheet. 218 ms is a spe c for material
65 * design (this is the minimum time a user is guaranteed to pay attention to something). 66 * design (this is the minimum time a user is guaranteed to pay attention to something).
66 */ 67 */
67 private static final long BASE_ANIMATION_DURATION_MS = 218; 68 private static final long BASE_ANIMATION_DURATION_MS = 218;
68 69
69 /** 70 /**
70 * The fraction of the way to the next state the sheet must be swiped to ani mate there when 71 * The fraction of the way to the next state the sheet must be swiped to ani mate there when
71 * released. A smaller value here means a smaller swipe is needed to move th e sheet around. 72 * released. A smaller value here means a smaller swipe is needed to move th e sheet around.
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
106 107
107 /** The height of the toolbar. */ 108 /** The height of the toolbar. */
108 private float mToolbarHeight; 109 private float mToolbarHeight;
109 110
110 /** The width of the view that contains the bottom sheet. */ 111 /** The width of the view that contains the bottom sheet. */
111 private float mContainerWidth; 112 private float mContainerWidth;
112 113
113 /** The height of the view that contains the bottom sheet. */ 114 /** The height of the view that contains the bottom sheet. */
114 private float mContainerHeight; 115 private float mContainerHeight;
115 116
116 /** The current sheet state. If the sheet is moving, this will be the target state. */ 117 /** The current state that the sheet is in. */
117 private int mCurrentState; 118 private int mCurrentState;
118 119
120 /** The target sheet state. This is the state that the sheet is currently mo ving to. */
121 private int mTargetState;
122
119 /** Used for getting the current tab. */ 123 /** Used for getting the current tab. */
120 private TabModelSelector mTabModelSelector; 124 private TabModelSelector mTabModelSelector;
121 125
122 /** The fullscreen manager for information about toolbar offsets. */ 126 /** The fullscreen manager for information about toolbar offsets. */
123 private ChromeFullscreenManager mFullscreenManager; 127 private ChromeFullscreenManager mFullscreenManager;
124 128
125 /** A handle to the content being shown by the sheet. */ 129 /** A handle to the content being shown by the sheet. */
126 private BottomSheetContent mSheetContent; 130 private BottomSheetContent mSheetContent;
127 131
128 /** A handle to the toolbar control container. */ 132 /** A handle to the toolbar control container. */
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
241 245
242 // Similarly, if the sheet is in the min position, don't move if the scroll is downward. 246 // Similarly, if the sheet is in the min position, don't move if the scroll is downward.
243 if (currentShownRatio <= getPeekRatio() && distanceY < 0) { 247 if (currentShownRatio <= getPeekRatio() && distanceY < 0) {
244 mIsScrolling = false; 248 mIsScrolling = false;
245 return false; 249 return false;
246 } 250 }
247 251
248 float newOffset = getSheetOffsetFromBottom() + distanceY; 252 float newOffset = getSheetOffsetFromBottom() + distanceY;
249 setSheetOffsetFromBottom(MathUtils.clamp(newOffset, getMinOffset(), getMaxOffset())); 253 setSheetOffsetFromBottom(MathUtils.clamp(newOffset, getMinOffset(), getMaxOffset()));
250 254
255 setInternalCurrentState(SHEET_STATE_SCROLLING);
251 mIsScrolling = true; 256 mIsScrolling = true;
252 return true; 257 return true;
253 } 258 }
254 259
255 @Override 260 @Override
256 public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { 261 public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
257 cancelAnimation(); 262 cancelAnimation();
258 263
259 // Figure out the projected state of the sheet and animate there. No te that a swipe up 264 // Figure out the projected state of the sheet and animate there. No te that a swipe up
260 // will have a negative velocity, swipe down will have a positive ve locity. Negate this 265 // will have a negative velocity, swipe down will have a positive ve locity. Negate this
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
381 // Make sure the size of the layout actually changed. 386 // Make sure the size of the layout actually changed.
382 if (bottom - top == oldBottom - oldTop && right - left == oldRig ht - oldLeft) { 387 if (bottom - top == oldBottom - oldTop && right - left == oldRig ht - oldLeft) {
383 return; 388 return;
384 } 389 }
385 390
386 mContainerWidth = right - left; 391 mContainerWidth = right - left;
387 mContainerHeight = bottom - top; 392 mContainerHeight = bottom - top;
388 updateSheetDimensions(); 393 updateSheetDimensions();
389 394
390 cancelAnimation(); 395 cancelAnimation();
391 setSheetState(mCurrentState, false); 396 setSheetState(mTargetState, false);
392 } 397 }
393 }); 398 });
394 399
395 // Listen to height changes on the toolbar. 400 // Listen to height changes on the toolbar.
396 controlContainer.addOnLayoutChangeListener(new View.OnLayoutChangeListen er() { 401 controlContainer.addOnLayoutChangeListener(new View.OnLayoutChangeListen er() {
397 @Override 402 @Override
398 public void onLayoutChange(View v, int left, int top, int right, int bottom, 403 public void onLayoutChange(View v, int left, int top, int right, int bottom,
399 int oldLeft, int oldTop, int oldRight, int oldBottom) { 404 int oldLeft, int oldTop, int oldRight, int oldBottom) {
400 // Make sure the size of the layout actually changed. 405 // Make sure the size of the layout actually changed.
401 if (bottom - top == oldBottom - oldTop && right - left == oldRig ht - oldLeft) { 406 if (bottom - top == oldBottom - oldTop && right - left == oldRig ht - oldLeft) {
402 return; 407 return;
403 } 408 }
404 409
405 mToolbarHeight = bottom - top; 410 mToolbarHeight = bottom - top;
406 updateSheetDimensions(); 411 updateSheetDimensions();
407 412
408 cancelAnimation(); 413 cancelAnimation();
409 setSheetState(mCurrentState, false); 414 setSheetState(mTargetState, false);
410 } 415 }
411 }); 416 });
412 417
413 mPlaceholder = new View(getContext()); 418 mPlaceholder = new View(getContext());
414 LayoutParams placeHolderParams = 419 LayoutParams placeHolderParams =
415 new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_P ARENT); 420 new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_P ARENT);
416 mPlaceholder.setBackgroundColor( 421 mPlaceholder.setBackgroundColor(
417 ApiCompatibilityUtils.getColor(getResources(), android.R.color.w hite)); 422 ApiCompatibilityUtils.getColor(getResources(), android.R.color.w hite));
418 mBottomSheetContentContainer.addView(mPlaceholder, placeHolderParams); 423 mBottomSheetContentContainer.addView(mPlaceholder, placeHolderParams);
419 424
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after
602 if (mSettleAnimator == null) return; 607 if (mSettleAnimator == null) return;
603 mSettleAnimator.cancel(); 608 mSettleAnimator.cancel();
604 mSettleAnimator = null; 609 mSettleAnimator = null;
605 } 610 }
606 611
607 /** 612 /**
608 * Creates the sheet's animation to a target state. 613 * Creates the sheet's animation to a target state.
609 * @param targetState The target state. 614 * @param targetState The target state.
610 */ 615 */
611 private void createSettleAnimation(@SheetState int targetState) { 616 private void createSettleAnimation(@SheetState int targetState) {
612 mCurrentState = targetState; 617 mTargetState = targetState;
613 mSettleAnimator = ValueAnimator.ofFloat( 618 mSettleAnimator = ValueAnimator.ofFloat(
614 getSheetOffsetFromBottom(), getSheetHeightForState(targetState)) ; 619 getSheetOffsetFromBottom(), getSheetHeightForState(targetState)) ;
615 mSettleAnimator.setDuration(BASE_ANIMATION_DURATION_MS); 620 mSettleAnimator.setDuration(BASE_ANIMATION_DURATION_MS);
616 mSettleAnimator.setInterpolator(mInterpolator); 621 mSettleAnimator.setInterpolator(mInterpolator);
617 622
618 // When the animation is canceled or ends, reset the handle to null. 623 // When the animation is canceled or ends, reset the handle to null.
619 mSettleAnimator.addListener(new AnimatorListenerAdapter() { 624 mSettleAnimator.addListener(new AnimatorListenerAdapter() {
620 @Override 625 @Override
621 public void onAnimationEnd(Animator animator) { 626 public void onAnimationEnd(Animator animator) {
622 mSettleAnimator = null; 627 mSettleAnimator = null;
628 setInternalCurrentState(mTargetState);
623 } 629 }
624 }); 630 });
625 631
626 mSettleAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListen er() { 632 mSettleAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListen er() {
627 @Override 633 @Override
628 public void onAnimationUpdate(ValueAnimator animator) { 634 public void onAnimationUpdate(ValueAnimator animator) {
629 setSheetOffsetFromBottom((Float) animator.getAnimatedValue()); 635 setSheetOffsetFromBottom((Float) animator.getAnimatedValue());
630 } 636 }
631 }); 637 });
632 638
633 mSettleAnimator.start(); 639 mSettleAnimator.start();
640 setInternalCurrentState(SHEET_STATE_SCROLLING);
634 } 641 }
635 642
636 /** 643 /**
637 * Gets the distance of a fling based on the velocity and the base animation time. This formula 644 * Gets the distance of a fling based on the velocity and the base animation time. This formula
638 * assumes the deceleration curve is quadratic (t^2), hence the displacement formula should be: 645 * assumes the deceleration curve is quadratic (t^2), hence the displacement formula should be:
639 * displacement = initialVelocity * duration / 2. 646 * displacement = initialVelocity * duration / 2.
640 * @param velocity The velocity of the fling. 647 * @param velocity The velocity of the fling.
641 * @return The distance the fling would cover. 648 * @return The distance the fling would cover.
642 */ 649 */
643 private float getFlingDistance(float velocity) { 650 private float getFlingDistance(float velocity) {
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
738 if (mLastPeekToHalfRatioSent < 1f || peekHalfRatio < 1f) { 745 if (mLastPeekToHalfRatioSent < 1f || peekHalfRatio < 1f) {
739 mLastPeekToHalfRatioSent = peekHalfRatio; 746 mLastPeekToHalfRatioSent = peekHalfRatio;
740 for (BottomSheetObserver o : mObservers) { 747 for (BottomSheetObserver o : mObservers) {
741 o.onTransitionPeekToHalf(peekHalfRatio); 748 o.onTransitionPeekToHalf(peekHalfRatio);
742 } 749 }
743 } 750 }
744 } 751 }
745 752
746 /** 753 /**
747 * Moves the sheet to the provided state. 754 * Moves the sheet to the provided state.
748 * @param state The state to move the panel to. 755 * @param state The state to move the panel to. This cannot be SHEET_STATE_S CROLLING.
749 * @param animate If true, the sheet will animate to the provided state, oth erwise it will 756 * @param animate If true, the sheet will animate to the provided state, oth erwise it will
750 * move there instantly. 757 * move there instantly.
751 */ 758 */
752 public void setSheetState(@SheetState int state, boolean animate) { 759 public void setSheetState(@SheetState int state, boolean animate) {
753 boolean stateChanged = state != mCurrentState; 760 assert state != SHEET_STATE_SCROLLING;
754 mCurrentState = state; 761 mTargetState = state;
755 762
756 if (animate) { 763 if (animate) {
757 createSettleAnimation(state); 764 createSettleAnimation(state);
758 } else { 765 } else {
759 setSheetOffsetFromBottom(getSheetHeightForState(state)); 766 setSheetOffsetFromBottom(getSheetHeightForState(state));
760 } 767 setInternalCurrentState(mTargetState);
761
762 if (!stateChanged) return;
763
764 for (BottomSheetObserver o : mObservers) {
765 o.onSheetStateChanged(mCurrentState);
766 } 768 }
767 } 769 }
768 770
769 /** 771 /**
770 * @return The current state of the bottom sheet. If the sheet is animating, this will be the 772 * @return The current state of the bottom sheet. If the sheet is animating, this will be the
771 * state the sheet is animating to. 773 * state the sheet is animating to.
772 */ 774 */
773 public int getSheetState() { 775 public int getSheetState() {
774 return mCurrentState; 776 return mCurrentState;
775 } 777 }
776 778
777 /** 779 /**
780 * Set the current state of the bottom sheet. This is for internal use to no tify observers of
781 * state change events.
782 * @param state The current state of the sheet.
783 */
784 private void setInternalCurrentState(@SheetState int state) {
785 boolean stateChanged = state != mCurrentState;
786 mCurrentState = state;
787
788 if (!stateChanged) return;
Theresa 2017/03/21 23:07:01 This early return can move up: if (state == mCurr
mdjones 2017/03/21 23:32:42 Done.
789
790 for (BottomSheetObserver o : mObservers) {
791 o.onSheetStateChanged(mCurrentState);
792 }
793 }
794
795 /**
778 * If the animation to settle the sheet in one of its states is running. 796 * If the animation to settle the sheet in one of its states is running.
779 * @return True if the animation is running. 797 * @return True if the animation is running.
780 */ 798 */
781 public boolean isRunningSettleAnimation() { 799 public boolean isRunningSettleAnimation() {
782 return mSettleAnimator != null; 800 return mSettleAnimator != null;
783 } 801 }
784 802
785 @VisibleForTesting 803 @VisibleForTesting
786 public BottomSheetContent getCurrentSheetContent() { 804 public BottomSheetContent getCurrentSheetContent() {
787 return mSheetContent; 805 return mSheetContent;
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
855 @Override 873 @Override
856 public void onFadingViewVisibilityChanged(boolean visible) {} 874 public void onFadingViewVisibilityChanged(boolean visible) {}
857 875
858 private boolean canMoveSheet() { 876 private boolean canMoveSheet() {
859 boolean isInOverviewMode = mTabModelSelector != null 877 boolean isInOverviewMode = mTabModelSelector != null
860 && (mTabModelSelector.getCurrentTab() == null 878 && (mTabModelSelector.getCurrentTab() == null
861 || mTabModelSelector.getCurrentTab().getActivity().is InOverviewMode()); 879 || mTabModelSelector.getCurrentTab().getActivity().is InOverviewMode());
862 return !isToolbarAndroidViewHidden() && !isInOverviewMode; 880 return !isToolbarAndroidViewHidden() && !isInOverviewMode;
863 } 881 }
864 } 882 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698