OLD | NEW |
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 15 matching lines...) Expand all Loading... |
26 import org.chromium.chrome.R; | 26 import org.chromium.chrome.R; |
27 import org.chromium.chrome.browser.NativePageHost; | 27 import org.chromium.chrome.browser.NativePageHost; |
28 import org.chromium.chrome.browser.TabLoadStatus; | 28 import org.chromium.chrome.browser.TabLoadStatus; |
29 import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager; | 29 import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager; |
30 import org.chromium.chrome.browser.ntp.NativePageFactory; | 30 import org.chromium.chrome.browser.ntp.NativePageFactory; |
31 import org.chromium.chrome.browser.tab.Tab; | 31 import org.chromium.chrome.browser.tab.Tab; |
32 import org.chromium.chrome.browser.tabmodel.TabModel; | 32 import org.chromium.chrome.browser.tabmodel.TabModel; |
33 import org.chromium.chrome.browser.tabmodel.TabModelSelector; | 33 import org.chromium.chrome.browser.tabmodel.TabModelSelector; |
34 import org.chromium.chrome.browser.util.MathUtils; | 34 import org.chromium.chrome.browser.util.MathUtils; |
35 import org.chromium.chrome.browser.widget.FadingBackgroundView; | 35 import org.chromium.chrome.browser.widget.FadingBackgroundView; |
| 36 import org.chromium.chrome.browser.widget.bottomsheet.BottomSheetContentControll
er.ContentType; |
36 import org.chromium.content_public.browser.LoadUrlParams; | 37 import org.chromium.content_public.browser.LoadUrlParams; |
37 | 38 |
38 import java.lang.annotation.Retention; | 39 import java.lang.annotation.Retention; |
39 import java.lang.annotation.RetentionPolicy; | 40 import java.lang.annotation.RetentionPolicy; |
40 | 41 |
41 /** | 42 /** |
42 * This class defines the bottom sheet that has multiple states and a persistent
ly showing toolbar. | 43 * This class defines the bottom sheet that has multiple states and a persistent
ly showing toolbar. |
43 * Namely, the states are: | 44 * Namely, the states are: |
44 * - PEEK: Only the toolbar is visible at the bottom of the screen. | 45 * - PEEK: Only the toolbar is visible at the bottom of the screen. |
45 * - 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. |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
144 | 145 |
145 /** | 146 /** |
146 * The default toolbar view. This is shown when the current bottom sheet con
tent doesn't have | 147 * The default toolbar view. This is shown when the current bottom sheet con
tent doesn't have |
147 * its own toolbar and when the bottom sheet is closed. | 148 * its own toolbar and when the bottom sheet is closed. |
148 */ | 149 */ |
149 private View mDefaultToolbarView; | 150 private View mDefaultToolbarView; |
150 | 151 |
151 /** The last non-default toolbar view that was attached to mToolbarHolder. *
/ | 152 /** The last non-default toolbar view that was attached to mToolbarHolder. *
/ |
152 private View mLastToolbarView; | 153 private View mLastToolbarView; |
153 | 154 |
| 155 /** Whether the sheet is currently open. */ |
| 156 private boolean mIsSheetOpen; |
| 157 |
154 /** | 158 /** |
155 * An interface defining content that can be displayed inside of the bottom
sheet for Chrome | 159 * An interface defining content that can be displayed inside of the bottom
sheet for Chrome |
156 * Home. | 160 * Home. |
157 */ | 161 */ |
158 public interface BottomSheetContent { | 162 public interface BottomSheetContent { |
159 /** | 163 /** |
160 * Gets the {@link View} that holds the content to be displayed in the C
hrome Home bottom | 164 * Gets the {@link View} that holds the content to be displayed in the C
hrome Home bottom |
161 * sheet. | 165 * sheet. |
162 * @return The content view. | 166 * @return The content view. |
163 */ | 167 */ |
(...skipping 11 matching lines...) Expand all Loading... |
175 | 179 |
176 /** | 180 /** |
177 * @return The vertical scroll offset of the content view. | 181 * @return The vertical scroll offset of the content view. |
178 */ | 182 */ |
179 int getVerticalScrollOffset(); | 183 int getVerticalScrollOffset(); |
180 | 184 |
181 /** | 185 /** |
182 * Called to destroy the BottomSheetContent when it is no longer in use. | 186 * Called to destroy the BottomSheetContent when it is no longer in use. |
183 */ | 187 */ |
184 void destroy(); | 188 void destroy(); |
| 189 |
| 190 /** |
| 191 * @return The {@link BottomSheetContentController.ContentType} for this
content. |
| 192 */ |
| 193 @ContentType |
| 194 int getType(); |
185 } | 195 } |
186 | 196 |
187 /** | 197 /** |
188 * This class is responsible for detecting swipe and scroll events on the bo
ttom sheet or | 198 * This class is responsible for detecting swipe and scroll events on the bo
ttom sheet or |
189 * ignoring them when appropriate. | 199 * ignoring them when appropriate. |
190 */ | 200 */ |
191 private class BottomSheetSwipeDetector extends GestureDetector.SimpleOnGestu
reListener { | 201 private class BottomSheetSwipeDetector extends GestureDetector.SimpleOnGestu
reListener { |
192 @Override | 202 @Override |
193 public boolean onDown(MotionEvent e) { | 203 public boolean onDown(MotionEvent e) { |
194 return true; | 204 return true; |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
264 * @param context An Android context. | 274 * @param context An Android context. |
265 * @param atts The XML attributes. | 275 * @param atts The XML attributes. |
266 */ | 276 */ |
267 public BottomSheet(Context context, AttributeSet atts) { | 277 public BottomSheet(Context context, AttributeSet atts) { |
268 super(context, atts); | 278 super(context, atts); |
269 | 279 |
270 mVelocityTracker = VelocityTracker.obtain(); | 280 mVelocityTracker = VelocityTracker.obtain(); |
271 | 281 |
272 mGestureDetector = new GestureDetector(context, new BottomSheetSwipeDete
ctor()); | 282 mGestureDetector = new GestureDetector(context, new BottomSheetSwipeDete
ctor()); |
273 mGestureDetector.setIsLongpressEnabled(false); | 283 mGestureDetector.setIsLongpressEnabled(false); |
| 284 |
| 285 addObserver(new BottomSheetMetrics()); |
274 } | 286 } |
275 | 287 |
276 @Override | 288 @Override |
277 public boolean onInterceptTouchEvent(MotionEvent e) { | 289 public boolean onInterceptTouchEvent(MotionEvent e) { |
278 if (!canMoveSheet()) return false; | 290 if (!canMoveSheet()) return false; |
279 | 291 |
280 // The incoming motion event may have been adjusted by the view sending
it down. Create a | 292 // The incoming motion event may have been adjusted by the view sending
it down. Create a |
281 // motion event with the raw (x, y) coordinates of the original so the g
esture detector | 293 // motion event with the raw (x, y) coordinates of the original so the g
esture detector |
282 // functions properly. | 294 // functions properly. |
283 mGestureDetector.onTouchEvent(createRawMotionEvent(e)); | 295 mGestureDetector.onTouchEvent(createRawMotionEvent(e)); |
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
498 mLastToolbarView = null; | 510 mLastToolbarView = null; |
499 } | 511 } |
500 | 512 |
501 if (mSheetContent.getToolbarView() != null) { | 513 if (mSheetContent.getToolbarView() != null) { |
502 mLastToolbarView = mSheetContent.getToolbarView(); | 514 mLastToolbarView = mSheetContent.getToolbarView(); |
503 mToolbarHolder.addView(mSheetContent.getToolbarView()); | 515 mToolbarHolder.addView(mSheetContent.getToolbarView()); |
504 mDefaultToolbarView.setVisibility(View.GONE); | 516 mDefaultToolbarView.setVisibility(View.GONE); |
505 } else { | 517 } else { |
506 mDefaultToolbarView.setVisibility(View.VISIBLE); | 518 mDefaultToolbarView.setVisibility(View.VISIBLE); |
507 } | 519 } |
| 520 |
| 521 for (BottomSheetObserver o : mObservers) { |
| 522 o.onSheetContentChanged(mSheetContent); |
| 523 } |
508 } | 524 } |
509 | 525 |
510 /** | 526 /** |
511 * Determines if a touch event is inside the toolbar. This assumes the toolb
ar is the full | 527 * Determines if a touch event is inside the toolbar. This assumes the toolb
ar is the full |
512 * width of the screen and that the toolbar is at the top of the bottom shee
t. | 528 * width of the screen and that the toolbar is at the top of the bottom shee
t. |
513 * @param e The motion event to test. | 529 * @param e The motion event to test. |
514 * @return True if the event occured in the toolbar region. | 530 * @return True if the event occured in the toolbar region. |
515 */ | 531 */ |
516 private boolean isTouchEventInToolbar(MotionEvent e) { | 532 private boolean isTouchEventInToolbar(MotionEvent e) { |
517 if (mControlContainer == null) return false; | 533 if (mControlContainer == null) return false; |
518 | 534 |
519 mControlContainer.getLocationInWindow(mLocationArray); | 535 mControlContainer.getLocationInWindow(mLocationArray); |
520 | 536 |
521 return e.getRawY() < mLocationArray[1] + mToolbarHeight; | 537 return e.getRawY() < mLocationArray[1] + mToolbarHeight; |
522 } | 538 } |
523 | 539 |
524 /** | 540 /** |
525 * A notification that the sheet is exiting the peek state into one that sho
ws content. | 541 * A notification that the sheet is exiting the peek state into one that sho
ws content. |
526 */ | 542 */ |
527 private void onSheetOpened() { | 543 private void onSheetOpened() { |
| 544 if (mIsSheetOpen) return; |
| 545 |
| 546 mIsSheetOpen = true; |
528 for (BottomSheetObserver o : mObservers) o.onSheetOpened(); | 547 for (BottomSheetObserver o : mObservers) o.onSheetOpened(); |
529 } | 548 } |
530 | 549 |
531 /** | 550 /** |
532 * A notification that the sheet has returned to the peeking state. | 551 * A notification that the sheet has returned to the peeking state. |
533 */ | 552 */ |
534 private void onSheetClosed() { | 553 private void onSheetClosed() { |
| 554 if (!mIsSheetOpen) return; |
| 555 |
| 556 mIsSheetOpen = false; |
535 for (BottomSheetObserver o : mObservers) o.onSheetClosed(); | 557 for (BottomSheetObserver o : mObservers) o.onSheetClosed(); |
536 } | 558 } |
537 | 559 |
538 /** | 560 /** |
539 * Creates an unadjusted version of a MotionEvent. | 561 * Creates an unadjusted version of a MotionEvent. |
540 * @param e The original event. | 562 * @param e The original event. |
541 * @return The unadjusted version of the event. | 563 * @return The unadjusted version of the event. |
542 */ | 564 */ |
543 private MotionEvent createRawMotionEvent(MotionEvent e) { | 565 private MotionEvent createRawMotionEvent(MotionEvent e) { |
544 MotionEvent rawEvent = MotionEvent.obtain(e); | 566 MotionEvent rawEvent = MotionEvent.obtain(e); |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
721 } | 743 } |
722 } | 744 } |
723 | 745 |
724 /** | 746 /** |
725 * Moves the sheet to the provided state. | 747 * Moves the sheet to the provided state. |
726 * @param state The state to move the panel to. | 748 * @param state The state to move the panel to. |
727 * @param animate If true, the sheet will animate to the provided state, oth
erwise it will | 749 * @param animate If true, the sheet will animate to the provided state, oth
erwise it will |
728 * move there instantly. | 750 * move there instantly. |
729 */ | 751 */ |
730 public void setSheetState(@SheetState int state, boolean animate) { | 752 public void setSheetState(@SheetState int state, boolean animate) { |
| 753 boolean stateChanged = state != mCurrentState; |
731 mCurrentState = state; | 754 mCurrentState = state; |
732 | 755 |
733 if (animate) { | 756 if (animate) { |
734 createSettleAnimation(state); | 757 createSettleAnimation(state); |
735 } else { | 758 } else { |
736 setSheetOffsetFromBottom(getSheetHeightForState(state)); | 759 setSheetOffsetFromBottom(getSheetHeightForState(state)); |
737 } | 760 } |
| 761 |
| 762 if (!stateChanged) return; |
| 763 |
| 764 for (BottomSheetObserver o : mObservers) { |
| 765 o.onSheetStateChanged(mCurrentState); |
| 766 } |
738 } | 767 } |
739 | 768 |
740 /** | 769 /** |
741 * @return The current state of the bottom sheet. If the sheet is animating,
this will be the | 770 * @return The current state of the bottom sheet. If the sheet is animating,
this will be the |
742 * state the sheet is animating to. | 771 * state the sheet is animating to. |
743 */ | 772 */ |
744 public int getSheetState() { | 773 public int getSheetState() { |
745 return mCurrentState; | 774 return mCurrentState; |
746 } | 775 } |
747 | 776 |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
826 @Override | 855 @Override |
827 public void onFadingViewVisibilityChanged(boolean visible) {} | 856 public void onFadingViewVisibilityChanged(boolean visible) {} |
828 | 857 |
829 private boolean canMoveSheet() { | 858 private boolean canMoveSheet() { |
830 boolean isInOverviewMode = mTabModelSelector != null | 859 boolean isInOverviewMode = mTabModelSelector != null |
831 && (mTabModelSelector.getCurrentTab() == null | 860 && (mTabModelSelector.getCurrentTab() == null |
832 || mTabModelSelector.getCurrentTab().getActivity().is
InOverviewMode()); | 861 || mTabModelSelector.getCurrentTab().getActivity().is
InOverviewMode()); |
833 return !isToolbarAndroidViewHidden() && !isInOverviewMode; | 862 return !isToolbarAndroidViewHidden() && !isInOverviewMode; |
834 } | 863 } |
835 } | 864 } |
OLD | NEW |