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

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: fix tests Created 3 years, 8 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 | chrome/android/javatests/src/org/chromium/chrome/browser/ntp/ChromeHomeNewTabPageTest.java » ('j') | 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.ObjectAnimator; 9 import android.animation.ObjectAnimator;
10 import android.animation.ValueAnimator; 10 import android.animation.ValueAnimator;
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
47 * - HALF: The sheet is expanded to consume around half of the screen. 47 * - HALF: The sheet is expanded to consume around half of the screen.
48 * - FULL: The sheet is expanded to its full height. 48 * - FULL: The sheet is expanded to its full height.
49 * 49 *
50 * All the computation in this file is based off of the bottom of the screen ins tead of the top 50 * All the computation in this file is based off of the bottom of the screen ins tead of the top
51 * for simplicity. This means that the bottom of the screen is 0 on the Y axis. 51 * for simplicity. This means that the bottom of the screen is 0 on the Y axis.
52 */ 52 */
53 53
54 public class BottomSheet 54 public class BottomSheet
55 extends FrameLayout implements FadingBackgroundView.FadingViewObserver, NativePageHost { 55 extends FrameLayout implements FadingBackgroundView.FadingViewObserver, NativePageHost {
56 /** The different states that the bottom sheet can have. */ 56 /** The different states that the bottom sheet can have. */
57 @IntDef({SHEET_STATE_PEEK, SHEET_STATE_HALF, SHEET_STATE_FULL}) 57 @IntDef({SHEET_STATE_PEEK, SHEET_STATE_HALF, SHEET_STATE_FULL, SHEET_STATE_S CROLLING})
58 @Retention(RetentionPolicy.SOURCE) 58 @Retention(RetentionPolicy.SOURCE)
59 public @interface SheetState {} 59 public @interface SheetState {}
60 public static final int SHEET_STATE_PEEK = 0; 60 public static final int SHEET_STATE_PEEK = 0;
61 public static final int SHEET_STATE_HALF = 1; 61 public static final int SHEET_STATE_HALF = 1;
62 public static final int SHEET_STATE_FULL = 2; 62 public static final int SHEET_STATE_FULL = 2;
63 public static final int SHEET_STATE_SCROLLING = 3;
63 64
64 /** 65 /**
65 * The base duration of the settling animation of the sheet. 218 ms is a spe c for material 66 * The base duration of the settling animation of the sheet. 218 ms is a spe c for material
66 * design (this is the minimum time a user is guaranteed to pay attention to something). 67 * design (this is the minimum time a user is guaranteed to pay attention to something).
67 */ 68 */
68 private static final long BASE_ANIMATION_DURATION_MS = 218; 69 private static final long BASE_ANIMATION_DURATION_MS = 218;
69 70
70 /** 71 /**
71 * The fraction of the way to the next state the sheet must be swiped to ani mate there when 72 * The fraction of the way to the next state the sheet must be swiped to ani mate there when
72 * released. This is the value used when there are 3 active states. A smalle r value here means 73 * released. This is the value used when there are 3 active states. A smalle r value here means
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
111 112
112 /** The height of the toolbar. */ 113 /** The height of the toolbar. */
113 private float mToolbarHeight; 114 private float mToolbarHeight;
114 115
115 /** The width of the view that contains the bottom sheet. */ 116 /** The width of the view that contains the bottom sheet. */
116 private float mContainerWidth; 117 private float mContainerWidth;
117 118
118 /** The height of the view that contains the bottom sheet. */ 119 /** The height of the view that contains the bottom sheet. */
119 private float mContainerHeight; 120 private float mContainerHeight;
120 121
121 /** The current sheet state. If the sheet is moving, this will be the target state. */ 122 /** The current state that the sheet is in. */
122 private int mCurrentState; 123 private int mCurrentState;
123 124
125 /** The target sheet state. This is the state that the sheet is currently mo ving to. */
126 private int mTargetState;
127
124 /** Used for getting the current tab. */ 128 /** Used for getting the current tab. */
125 private TabModelSelector mTabModelSelector; 129 private TabModelSelector mTabModelSelector;
126 130
127 /** The fullscreen manager for information about toolbar offsets. */ 131 /** The fullscreen manager for information about toolbar offsets. */
128 private ChromeFullscreenManager mFullscreenManager; 132 private ChromeFullscreenManager mFullscreenManager;
129 133
130 /** A handle to the content being shown by the sheet. */ 134 /** A handle to the content being shown by the sheet. */
131 private BottomSheetContent mSheetContent; 135 private BottomSheetContent mSheetContent;
132 136
133 /** A handle to the toolbar control container. */ 137 /** A handle to the toolbar control container. */
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
243 247
244 // Similarly, if the sheet is in the min position, don't move if the scroll is downward. 248 // Similarly, if the sheet is in the min position, don't move if the scroll is downward.
245 if (currentShownRatio <= getPeekRatio() && distanceY < 0) { 249 if (currentShownRatio <= getPeekRatio() && distanceY < 0) {
246 mIsScrolling = false; 250 mIsScrolling = false;
247 return false; 251 return false;
248 } 252 }
249 253
250 float newOffset = getSheetOffsetFromBottom() + distanceY; 254 float newOffset = getSheetOffsetFromBottom() + distanceY;
251 setSheetOffsetFromBottom(MathUtils.clamp(newOffset, getMinOffset(), getMaxOffset())); 255 setSheetOffsetFromBottom(MathUtils.clamp(newOffset, getMinOffset(), getMaxOffset()));
252 256
257 setInternalCurrentState(SHEET_STATE_SCROLLING);
253 mIsScrolling = true; 258 mIsScrolling = true;
254 return true; 259 return true;
255 } 260 }
256 261
257 @Override 262 @Override
258 public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { 263 public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
259 cancelAnimation(); 264 cancelAnimation();
260 265
261 // Figure out the projected state of the sheet and animate there. No te that a swipe up 266 // Figure out the projected state of the sheet and animate there. No te that a swipe up
262 // will have a negative velocity, swipe down will have a positive ve locity. Negate this 267 // 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
383 // Make sure the size of the layout actually changed. 388 // Make sure the size of the layout actually changed.
384 if (bottom - top == oldBottom - oldTop && right - left == oldRig ht - oldLeft) { 389 if (bottom - top == oldBottom - oldTop && right - left == oldRig ht - oldLeft) {
385 return; 390 return;
386 } 391 }
387 392
388 mContainerWidth = right - left; 393 mContainerWidth = right - left;
389 mContainerHeight = bottom - top; 394 mContainerHeight = bottom - top;
390 updateSheetDimensions(); 395 updateSheetDimensions();
391 396
392 cancelAnimation(); 397 cancelAnimation();
393 setSheetState(mCurrentState, false); 398 setSheetState(mTargetState, false);
394 } 399 }
395 }); 400 });
396 401
397 // Listen to height changes on the toolbar. 402 // Listen to height changes on the toolbar.
398 controlContainer.addOnLayoutChangeListener(new View.OnLayoutChangeListen er() { 403 controlContainer.addOnLayoutChangeListener(new View.OnLayoutChangeListen er() {
399 @Override 404 @Override
400 public void onLayoutChange(View v, int left, int top, int right, int bottom, 405 public void onLayoutChange(View v, int left, int top, int right, int bottom,
401 int oldLeft, int oldTop, int oldRight, int oldBottom) { 406 int oldLeft, int oldTop, int oldRight, int oldBottom) {
402 // Make sure the size of the layout actually changed. 407 // Make sure the size of the layout actually changed.
403 if (bottom - top == oldBottom - oldTop && right - left == oldRig ht - oldLeft) { 408 if (bottom - top == oldBottom - oldTop && right - left == oldRig ht - oldLeft) {
404 return; 409 return;
405 } 410 }
406 411
407 mToolbarHeight = bottom - top; 412 mToolbarHeight = bottom - top;
408 updateSheetDimensions(); 413 updateSheetDimensions();
409 414
410 cancelAnimation(); 415 cancelAnimation();
411 setSheetState(mCurrentState, false); 416 setSheetState(mTargetState, false);
412 } 417 }
413 }); 418 });
414 419
415 mPlaceholder = new View(getContext()); 420 mPlaceholder = new View(getContext());
416 LayoutParams placeHolderParams = 421 LayoutParams placeHolderParams =
417 new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_P ARENT); 422 new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_P ARENT);
418 mPlaceholder.setBackgroundColor( 423 mPlaceholder.setBackgroundColor(
419 ApiCompatibilityUtils.getColor(getResources(), android.R.color.w hite)); 424 ApiCompatibilityUtils.getColor(getResources(), android.R.color.w hite));
420 mBottomSheetContentContainer.addView(mPlaceholder, placeHolderParams); 425 mBottomSheetContentContainer.addView(mPlaceholder, placeHolderParams);
421 426
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after
648 if (mSettleAnimator == null) return; 653 if (mSettleAnimator == null) return;
649 mSettleAnimator.cancel(); 654 mSettleAnimator.cancel();
650 mSettleAnimator = null; 655 mSettleAnimator = null;
651 } 656 }
652 657
653 /** 658 /**
654 * Creates the sheet's animation to a target state. 659 * Creates the sheet's animation to a target state.
655 * @param targetState The target state. 660 * @param targetState The target state.
656 */ 661 */
657 private void createSettleAnimation(@SheetState int targetState) { 662 private void createSettleAnimation(@SheetState int targetState) {
658 mCurrentState = targetState; 663 mTargetState = targetState;
659 mSettleAnimator = ValueAnimator.ofFloat( 664 mSettleAnimator = ValueAnimator.ofFloat(
660 getSheetOffsetFromBottom(), getSheetHeightForState(targetState)) ; 665 getSheetOffsetFromBottom(), getSheetHeightForState(targetState)) ;
661 mSettleAnimator.setDuration(BASE_ANIMATION_DURATION_MS); 666 mSettleAnimator.setDuration(BASE_ANIMATION_DURATION_MS);
662 mSettleAnimator.setInterpolator(mInterpolator); 667 mSettleAnimator.setInterpolator(mInterpolator);
663 668
664 // When the animation is canceled or ends, reset the handle to null. 669 // When the animation is canceled or ends, reset the handle to null.
665 mSettleAnimator.addListener(new AnimatorListenerAdapter() { 670 mSettleAnimator.addListener(new AnimatorListenerAdapter() {
666 @Override 671 @Override
667 public void onAnimationEnd(Animator animator) { 672 public void onAnimationEnd(Animator animator) {
668 mSettleAnimator = null; 673 mSettleAnimator = null;
674 setInternalCurrentState(mTargetState);
669 } 675 }
670 }); 676 });
671 677
672 mSettleAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListen er() { 678 mSettleAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListen er() {
673 @Override 679 @Override
674 public void onAnimationUpdate(ValueAnimator animator) { 680 public void onAnimationUpdate(ValueAnimator animator) {
675 setSheetOffsetFromBottom((Float) animator.getAnimatedValue()); 681 setSheetOffsetFromBottom((Float) animator.getAnimatedValue());
676 } 682 }
677 }); 683 });
678 684
679 mSettleAnimator.start(); 685 mSettleAnimator.start();
686 setInternalCurrentState(SHEET_STATE_SCROLLING);
680 } 687 }
681 688
682 /** 689 /**
683 * Gets the distance of a fling based on the velocity and the base animation time. This formula 690 * Gets the distance of a fling based on the velocity and the base animation time. This formula
684 * assumes the deceleration curve is quadratic (t^2), hence the displacement formula should be: 691 * assumes the deceleration curve is quadratic (t^2), hence the displacement formula should be:
685 * displacement = initialVelocity * duration / 2. 692 * displacement = initialVelocity * duration / 2.
686 * @param velocity The velocity of the fling. 693 * @param velocity The velocity of the fling.
687 * @return The distance the fling would cover. 694 * @return The distance the fling would cover.
688 */ 695 */
689 private float getFlingDistance(float velocity) { 696 private float getFlingDistance(float velocity) {
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
784 if (mLastPeekToHalfRatioSent < 1f || peekHalfRatio < 1f) { 791 if (mLastPeekToHalfRatioSent < 1f || peekHalfRatio < 1f) {
785 mLastPeekToHalfRatioSent = peekHalfRatio; 792 mLastPeekToHalfRatioSent = peekHalfRatio;
786 for (BottomSheetObserver o : mObservers) { 793 for (BottomSheetObserver o : mObservers) {
787 o.onTransitionPeekToHalf(peekHalfRatio); 794 o.onTransitionPeekToHalf(peekHalfRatio);
788 } 795 }
789 } 796 }
790 } 797 }
791 798
792 /** 799 /**
793 * Moves the sheet to the provided state. 800 * Moves the sheet to the provided state.
794 * @param state The state to move the panel to. 801 * @param state The state to move the panel to. This cannot be SHEET_STATE_S CROLLING.
795 * @param animate If true, the sheet will animate to the provided state, oth erwise it will 802 * @param animate If true, the sheet will animate to the provided state, oth erwise it will
796 * move there instantly. 803 * move there instantly.
797 */ 804 */
798 public void setSheetState(@SheetState int state, boolean animate) { 805 public void setSheetState(@SheetState int state, boolean animate) {
799 boolean stateChanged = state != mCurrentState; 806 assert state != SHEET_STATE_SCROLLING;
800 mCurrentState = state; 807 mTargetState = state;
801 808
802 if (animate) { 809 if (animate) {
803 createSettleAnimation(state); 810 createSettleAnimation(state);
804 } else { 811 } else {
805 setSheetOffsetFromBottom(getSheetHeightForState(state)); 812 setSheetOffsetFromBottom(getSheetHeightForState(state));
806 } 813 setInternalCurrentState(mTargetState);
807
808 if (!stateChanged) return;
809
810 for (BottomSheetObserver o : mObservers) {
811 o.onSheetStateChanged(mCurrentState);
812 } 814 }
813 } 815 }
814 816
815 /** 817 /**
816 * @return The current state of the bottom sheet. If the sheet is animating, this will be the 818 * @return The current state of the bottom sheet. If the sheet is animating, this will be the
817 * state the sheet is animating to. 819 * state the sheet is animating to.
818 */ 820 */
819 public int getSheetState() { 821 public int getSheetState() {
820 return mCurrentState; 822 return mCurrentState;
821 } 823 }
822 824
823 /** 825 /**
826 * Set the current state of the bottom sheet. This is for internal use to no tify observers of
827 * state change events.
828 * @param state The current state of the sheet.
829 */
830 private void setInternalCurrentState(@SheetState int state) {
831 if (state == mCurrentState) return;
832 mCurrentState = state;
833
834 for (BottomSheetObserver o : mObservers) {
835 o.onSheetStateChanged(mCurrentState);
836 }
837 }
838
839 /**
824 * If the animation to settle the sheet in one of its states is running. 840 * If the animation to settle the sheet in one of its states is running.
825 * @return True if the animation is running. 841 * @return True if the animation is running.
826 */ 842 */
827 public boolean isRunningSettleAnimation() { 843 public boolean isRunningSettleAnimation() {
828 return mSettleAnimator != null; 844 return mSettleAnimator != null;
829 } 845 }
830 846
831 @VisibleForTesting 847 @VisibleForTesting
832 public BottomSheetContent getCurrentSheetContent() { 848 public BottomSheetContent getCurrentSheetContent() {
833 return mSheetContent; 849 return mSheetContent;
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
906 @Override 922 @Override
907 public void onFadingViewVisibilityChanged(boolean visible) {} 923 public void onFadingViewVisibilityChanged(boolean visible) {}
908 924
909 private boolean canMoveSheet() { 925 private boolean canMoveSheet() {
910 boolean isInOverviewMode = mTabModelSelector != null 926 boolean isInOverviewMode = mTabModelSelector != null
911 && (mTabModelSelector.getCurrentTab() == null 927 && (mTabModelSelector.getCurrentTab() == null
912 || mTabModelSelector.getCurrentTab().getActivity().is InOverviewMode()); 928 || mTabModelSelector.getCurrentTab().getActivity().is InOverviewMode());
913 return !isToolbarAndroidViewHidden() && !isInOverviewMode; 929 return !isToolbarAndroidViewHidden() && !isInOverviewMode;
914 } 930 }
915 } 931 }
OLDNEW
« no previous file with comments | « no previous file | chrome/android/javatests/src/org/chromium/chrome/browser/ntp/ChromeHomeNewTabPageTest.java » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698