| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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.ntp; | 5 package org.chromium.chrome.browser.ntp; |
| 6 | 6 |
| 7 import android.annotation.SuppressLint; | 7 import android.annotation.SuppressLint; |
| 8 import android.content.Context; | 8 import android.content.Context; |
| 9 import android.content.res.Configuration; | 9 import android.content.res.Configuration; |
| 10 import android.content.res.Resources; | 10 import android.content.res.Resources; |
| 11 import android.graphics.Bitmap; | 11 import android.graphics.Bitmap; |
| 12 import android.graphics.BitmapFactory; | 12 import android.graphics.BitmapFactory; |
| 13 import android.graphics.Canvas; | 13 import android.graphics.Canvas; |
| 14 import android.graphics.Color; | 14 import android.graphics.Color; |
| 15 import android.graphics.Point; | |
| 16 import android.graphics.Rect; | 15 import android.graphics.Rect; |
| 17 import android.graphics.drawable.BitmapDrawable; | 16 import android.graphics.drawable.BitmapDrawable; |
| 18 import android.support.v4.graphics.drawable.RoundedBitmapDrawable; | 17 import android.support.v4.graphics.drawable.RoundedBitmapDrawable; |
| 19 import android.support.v4.graphics.drawable.RoundedBitmapDrawableFactory; | 18 import android.support.v4.graphics.drawable.RoundedBitmapDrawableFactory; |
| 20 import android.support.v7.widget.RecyclerView; | 19 import android.support.v7.widget.RecyclerView; |
| 21 import android.support.v7.widget.helper.ItemTouchHelper; | 20 import android.support.v7.widget.helper.ItemTouchHelper; |
| 22 import android.text.Editable; | 21 import android.text.Editable; |
| 23 import android.text.TextUtils; | 22 import android.text.TextUtils; |
| 24 import android.text.TextWatcher; | 23 import android.text.TextWatcher; |
| 25 import android.util.AttributeSet; | 24 import android.util.AttributeSet; |
| (...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 387 } else { | 386 } else { |
| 388 ((ViewGroup) toolbar.getParent()).removeView(toolbar); | 387 ((ViewGroup) toolbar.getParent()).removeView(toolbar); |
| 389 MarginLayoutParams params = (MarginLayoutParams) getWrapperView().ge
tLayoutParams(); | 388 MarginLayoutParams params = (MarginLayoutParams) getWrapperView().ge
tLayoutParams(); |
| 390 params.bottomMargin = 0; | 389 params.bottomMargin = 0; |
| 391 } | 390 } |
| 392 } | 391 } |
| 393 | 392 |
| 394 private void updateSearchBoxOnScroll() { | 393 private void updateSearchBoxOnScroll() { |
| 395 if (mDisableUrlFocusChangeAnimations) return; | 394 if (mDisableUrlFocusChangeAnimations) return; |
| 396 | 395 |
| 396 float toolbarTransitionPercentage; |
| 397 // During startup the view may not be fully initialized, so we only calc
ulate the current |
| 398 // percentage if some basic view properties are sane. |
| 399 if (getWrapperView().getHeight() == 0 || mSearchBoxView.getTop() == 0) { |
| 400 toolbarTransitionPercentage = 0f; |
| 401 } else if (!mUseCardsUi) { |
| 402 toolbarTransitionPercentage = |
| 403 MathUtils.clamp(getVerticalScroll() / (float) mSearchBoxView
.getTop(), 0f, 1f); |
| 404 } else { |
| 405 if (!mRecyclerView.isFirstItemVisible()) { |
| 406 // getVerticalScroll is valid only for the RecyclerView if the f
irst item is |
| 407 // visible. Luckily, if the first item is not visible, we know t
he toolbar |
| 408 // transition should be 100%. |
| 409 toolbarTransitionPercentage = 1f; |
| 410 } else { |
| 411 final int scrollY = getVerticalScroll(); |
| 412 final int top = mSearchBoxView.getTop(); // Relative to mNewTab
PageLayout. |
| 413 final int transitionLength = getResources() |
| 414 .getDimensionPixelSize(R.dimen.ntp_search_box_transition
_length); |
| 415 |
| 416 // |scrollY - top| gives the distance the search bar is from the
top of the screen. |
| 417 toolbarTransitionPercentage = MathUtils.clamp( |
| 418 (scrollY - top + transitionLength) / (float) transitionL
ength, 0f, 1f); |
| 419 } |
| 420 } |
| 421 |
| 422 updateVisualsForToolbarTransition(toolbarTransitionPercentage); |
| 423 |
| 397 if (mSearchBoxScrollListener != null) { | 424 if (mSearchBoxScrollListener != null) { |
| 398 mSearchBoxScrollListener.onNtpScrollChanged(getToolbarTransitionPerc
entage()); | 425 mSearchBoxScrollListener.onNtpScrollChanged(toolbarTransitionPercent
age); |
| 399 } | 426 } |
| 400 } | 427 } |
| 401 | 428 |
| 402 /** | |
| 403 * Calculates the percentage (between 0 and 1) of the transition from the se
arch box to the | |
| 404 * omnibox at the top of the New Tab Page, which is determined by the amount
of scrolling and | |
| 405 * the position of the search box. | |
| 406 * | |
| 407 * @return the transition percentage | |
| 408 */ | |
| 409 private float getToolbarTransitionPercentage() { | |
| 410 // During startup the view may not be fully initialized, so we only calc
ulate the current | |
| 411 // percentage if some basic view properties (height of the containing vi
ew, position of the | |
| 412 // search box) are sane. | |
| 413 if (getWrapperView().getHeight() == 0) return 0f; | |
| 414 | |
| 415 int searchBoxTop = mSearchBoxView.getTop(); | |
| 416 if (searchBoxTop == 0) return 0f; | |
| 417 | |
| 418 // For all other calculations, add the search box padding, because it de
fines where the | |
| 419 // visible "border" of the search box is. | |
| 420 searchBoxTop += mSearchBoxView.getPaddingTop(); | |
| 421 | |
| 422 if (!mUseCardsUi) { | |
| 423 return MathUtils.clamp(getVerticalScroll() / (float) searchBoxTop, 0
f, 1f); | |
| 424 } | |
| 425 | |
| 426 if (!mRecyclerView.isFirstItemVisible()) { | |
| 427 // getVerticalScroll is valid only for the RecyclerView if the first
item is | |
| 428 // visible. If the first item is not visible, we know the toolbar tr
ansition | |
| 429 // should be 100%. | |
| 430 return 1f; | |
| 431 } | |
| 432 | |
| 433 final int scrollY = getVerticalScroll(); | |
| 434 final float transitionLength = | |
| 435 getResources().getDimension(R.dimen.ntp_search_box_transition_le
ngth); | |
| 436 | |
| 437 // |scrollY - searchBoxTop| gives the distance the search bar is from th
e top of the screen. | |
| 438 return MathUtils.clamp( | |
| 439 (scrollY - searchBoxTop + transitionLength) / transitionLength,
0f, 1f); | |
| 440 } | |
| 441 | |
| 442 private ViewGroup getWrapperView() { | 429 private ViewGroup getWrapperView() { |
| 443 return mUseCardsUi ? mRecyclerView : mScrollView; | 430 return mUseCardsUi ? mRecyclerView : mScrollView; |
| 444 } | 431 } |
| 445 | 432 |
| 446 /** | 433 /** |
| 447 * Get the number of listed items (visible or not) for the given type. | 434 * Get the number of listed items (visible or not) for the given type. |
| 448 * @param newTabPageListItemViewType the item type to count. | 435 * @param newTabPageListItemViewType the item type to count. |
| 449 */ | 436 */ |
| 450 public int getViewCountMatchingViewType( | 437 public int getViewCountMatchingViewType( |
| 451 @NewTabPageListItem.ViewType int newTabPageListItemViewType) { | 438 @NewTabPageListItem.ViewType int newTabPageListItemViewType) { |
| (...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 667 private void onUrlFocusAnimationChanged() { | 654 private void onUrlFocusAnimationChanged() { |
| 668 if (mDisableUrlFocusChangeAnimations) return; | 655 if (mDisableUrlFocusChangeAnimations) return; |
| 669 | 656 |
| 670 float percent = mSearchProviderHasLogo ? mUrlFocusChangePercent : 0; | 657 float percent = mSearchProviderHasLogo ? mUrlFocusChangePercent : 0; |
| 671 // Only apply the scrolling offset when not using the cards UI, as there
we will either snap | 658 // Only apply the scrolling offset when not using the cards UI, as there
we will either snap |
| 672 // to the top of the page (with scrolling offset 0), or snap to below th
e fold, where Most | 659 // to the top of the page (with scrolling offset 0), or snap to below th
e fold, where Most |
| 673 // Likely items are not visible anymore, so they will stay out of sight. | 660 // Likely items are not visible anymore, so they will stay out of sight. |
| 674 int scrollOffset = mUseCardsUi ? 0 : mScrollView.getScrollY(); | 661 int scrollOffset = mUseCardsUi ? 0 : mScrollView.getScrollY(); |
| 675 mNewTabPageLayout.setTranslationY(percent * (-mMostVisitedLayout.getTop(
) + scrollOffset | 662 mNewTabPageLayout.setTranslationY(percent * (-mMostVisitedLayout.getTop(
) + scrollOffset |
| 676 + mNewTabPageLayout.
getPaddingTop())); | 663 + mNewTabPageLayout.
getPaddingTop())); |
| 664 updateVisualsForToolbarTransition(percent); |
| 677 } | 665 } |
| 678 | 666 |
| 679 /** | 667 /** |
| 680 * Updates the opacity of the search box when scrolling. | 668 * Updates the opacity of the fake omnibox and Google logo when scrolling. |
| 681 * | 669 * @param transitionPercentage |
| 682 * @param alpha opacity (alpha) value to use. | |
| 683 */ | 670 */ |
| 684 public void setSearchBoxAlpha(float alpha) { | 671 private void updateVisualsForToolbarTransition(float transitionPercentage) { |
| 685 mSearchBoxView.setAlpha(alpha); | 672 // Complete the full alpha transition in the first 40% of the animation. |
| 686 } | 673 float searchUiAlpha = |
| 674 transitionPercentage >= 0.4f ? 0f : (0.4f - transitionPercentage
) * 2.5f; |
| 675 // Ensure there are no rounding issues when the animation percent is 0. |
| 676 if (transitionPercentage == 0f) searchUiAlpha = 1f; |
| 687 | 677 |
| 688 /** | 678 if (!mUseCardsUi) { |
| 689 * Updates the opacity of the search provider logo when scrolling. | 679 mSearchProviderLogoView.setAlpha(searchUiAlpha); |
| 690 * | 680 } |
| 691 * @param alpha opacity (alpha) value to use. | 681 mSearchBoxView.setAlpha(searchUiAlpha); |
| 692 */ | |
| 693 public void setSearchProviderLogoAlpha(float alpha) { | |
| 694 mSearchProviderLogoView.setAlpha(alpha); | |
| 695 } | 682 } |
| 696 | 683 |
| 697 /** | 684 /** |
| 698 * Get the bounds of the search box in relation to the top level NewTabPage
view. | 685 * Get the bounds of the search box in relation to the top level NewTabPage
view. |
| 699 * | 686 * |
| 700 * @param bounds The current drawing location of the search box. | 687 * @param originalBounds The bounding region of the search box without exter
nal transforms |
| 701 * @param translation The translation applied to the search box by the paren
t view hierarchy up | 688 * applied. The delta between this and the transforme
d bounds determines |
| 702 * to the NewTabPage view. | 689 * the amount of scroll applied to this view. |
| 690 * @param transformedBounds The bounding region of the search box including
any transforms |
| 691 * applied by the parent view hierarchy up to the N
ewTabPage view. |
| 692 * This more accurately reflects the current drawin
g location of the |
| 693 * search box. |
| 703 */ | 694 */ |
| 704 void getSearchBoxBounds(Rect bounds, Point translation) { | 695 void getSearchBoxBounds(Rect originalBounds, Rect transformedBounds) { |
| 705 int searchBoxX = (int) mSearchBoxView.getX(); | 696 int searchBoxX = (int) mSearchBoxView.getX(); |
| 706 int searchBoxY = (int) mSearchBoxView.getY(); | 697 int searchBoxY = (int) mSearchBoxView.getY(); |
| 707 | 698 |
| 708 bounds.set(searchBoxX + mSearchBoxView.getPaddingLeft(), | 699 originalBounds.set( |
| 700 searchBoxX + mSearchBoxView.getPaddingLeft(), |
| 709 searchBoxY + mSearchBoxView.getPaddingTop(), | 701 searchBoxY + mSearchBoxView.getPaddingTop(), |
| 710 searchBoxX + mSearchBoxView.getWidth() - mSearchBoxView.getPaddi
ngRight(), | 702 searchBoxX + mSearchBoxView.getWidth() - mSearchBoxView.getPaddi
ngRight(), |
| 711 searchBoxY + mSearchBoxView.getHeight() - mSearchBoxView.getPadd
ingBottom()); | 703 searchBoxY + mSearchBoxView.getHeight() - mSearchBoxView.getPadd
ingBottom()); |
| 712 | 704 |
| 713 translation.set(0, 0); | 705 transformedBounds.set(originalBounds); |
| 714 | |
| 715 View view = (View) mSearchBoxView.getParent(); | 706 View view = (View) mSearchBoxView.getParent(); |
| 716 while (view != null) { | 707 while (view != null) { |
| 717 translation.offset(-view.getScrollX(), -view.getScrollY()); | 708 transformedBounds.offset(-view.getScrollX(), -view.getScrollY()); |
| 718 if (view == this) break; | 709 if (view == this) break; |
| 719 translation.offset((int) view.getX(), (int) view.getY()); | 710 transformedBounds.offset((int) view.getX(), (int) view.getY()); |
| 720 view = (View) view.getParent(); | 711 view = (View) view.getParent(); |
| 721 } | 712 } |
| 722 bounds.offset(translation.x, translation.y); | |
| 723 } | 713 } |
| 724 | 714 |
| 725 /** | 715 /** |
| 726 * Sets the listener for search box scroll changes. | 716 * Sets the listener for search box scroll changes. |
| 727 * @param listener The listener to be notified on changes. | 717 * @param listener The listener to be notified on changes. |
| 728 */ | 718 */ |
| 729 void setSearchBoxScrollListener(OnSearchBoxScrollListener listener) { | 719 void setSearchBoxScrollListener(OnSearchBoxScrollListener listener) { |
| 730 mSearchBoxScrollListener = listener; | 720 mSearchBoxScrollListener = listener; |
| 731 if (mSearchBoxScrollListener != null) updateSearchBoxOnScroll(); | 721 if (mSearchBoxScrollListener != null) updateSearchBoxOnScroll(); |
| 732 } | 722 } |
| (...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1105 } | 1095 } |
| 1106 | 1096 |
| 1107 private int getVerticalScroll() { | 1097 private int getVerticalScroll() { |
| 1108 if (mUseCardsUi) { | 1098 if (mUseCardsUi) { |
| 1109 return mRecyclerView.computeVerticalScrollOffset(); | 1099 return mRecyclerView.computeVerticalScrollOffset(); |
| 1110 } else { | 1100 } else { |
| 1111 return mScrollView.getScrollY(); | 1101 return mScrollView.getScrollY(); |
| 1112 } | 1102 } |
| 1113 } | 1103 } |
| 1114 } | 1104 } |
| OLD | NEW |