OLD | NEW |
(Empty) | |
| 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 |
| 3 // found in the LICENSE file. |
| 4 |
| 5 package org.chromium.chrome.browser.toolbar; |
| 6 |
| 7 import android.animation.Animator; |
| 8 import android.animation.AnimatorListenerAdapter; |
| 9 import android.animation.AnimatorSet; |
| 10 import android.animation.ObjectAnimator; |
| 11 import android.animation.ValueAnimator; |
| 12 import android.animation.ValueAnimator.AnimatorUpdateListener; |
| 13 import android.annotation.SuppressLint; |
| 14 import android.content.Context; |
| 15 import android.content.res.ColorStateList; |
| 16 import android.content.res.Resources; |
| 17 import android.graphics.Canvas; |
| 18 import android.graphics.Color; |
| 19 import android.graphics.Point; |
| 20 import android.graphics.PorterDuff; |
| 21 import android.graphics.Rect; |
| 22 import android.graphics.drawable.BitmapDrawable; |
| 23 import android.graphics.drawable.ColorDrawable; |
| 24 import android.graphics.drawable.Drawable; |
| 25 import android.graphics.drawable.TransitionDrawable; |
| 26 import android.os.Build; |
| 27 import android.os.SystemClock; |
| 28 import android.util.AttributeSet; |
| 29 import android.util.Property; |
| 30 import android.view.Gravity; |
| 31 import android.view.MotionEvent; |
| 32 import android.view.View; |
| 33 import android.view.View.OnClickListener; |
| 34 import android.view.View.OnLongClickListener; |
| 35 import android.view.ViewGroup; |
| 36 import android.view.WindowManager; |
| 37 import android.view.animation.LinearInterpolator; |
| 38 import android.widget.FrameLayout; |
| 39 import android.widget.ImageView; |
| 40 import android.widget.TextView; |
| 41 import android.widget.Toast; |
| 42 |
| 43 import com.google.android.apps.chrome.R; |
| 44 |
| 45 import org.chromium.base.ApiCompatibilityUtils; |
| 46 import org.chromium.base.SysUtils; |
| 47 import org.chromium.base.VisibleForTesting; |
| 48 import org.chromium.base.metrics.RecordUserAction; |
| 49 import org.chromium.chrome.browser.Tab; |
| 50 import org.chromium.chrome.browser.compositor.Invalidator; |
| 51 import org.chromium.chrome.browser.document.BrandColorUtils; |
| 52 import org.chromium.chrome.browser.ntp.NewTabPage; |
| 53 import org.chromium.chrome.browser.omnibox.LocationBar; |
| 54 import org.chromium.chrome.browser.omnibox.LocationBarPhone; |
| 55 import org.chromium.chrome.browser.omnibox.UrlContainer; |
| 56 import org.chromium.chrome.browser.partnercustomizations.HomepageManager; |
| 57 import org.chromium.chrome.browser.util.FeatureUtilities; |
| 58 import org.chromium.chrome.browser.util.MathUtils; |
| 59 import org.chromium.chrome.browser.widget.TintedImageButton; |
| 60 import org.chromium.chrome.browser.widget.newtab.NewTabButton; |
| 61 import org.chromium.ui.base.LocalizationUtils; |
| 62 import org.chromium.ui.interpolators.BakedBezierInterpolator; |
| 63 |
| 64 import java.util.ArrayList; |
| 65 import java.util.HashSet; |
| 66 import java.util.List; |
| 67 import java.util.Set; |
| 68 |
| 69 /** |
| 70 * Phone specific toolbar implementation. |
| 71 */ |
| 72 public class ToolbarPhone extends ToolbarLayout |
| 73 implements Invalidator.Client, OnClickListener, OnLongClickListener, |
| 74 NewTabPage.OnSearchBoxScrollListener { |
| 75 |
| 76 public static final int URL_FOCUS_CHANGE_ANIMATION_DURATION_MS = 250; |
| 77 private static final int URL_FOCUS_TOOLBAR_BUTTONS_TRANSLATION_X_DP = 10; |
| 78 private static final int URL_FOCUS_TOOLBAR_BUTTONS_DURATION_MS = 100; |
| 79 private static final int URL_CLEAR_FOCUS_TABSTACK_DELAY_MS = 200; |
| 80 private static final int URL_CLEAR_FOCUS_MENU_DELAY_MS = 250; |
| 81 |
| 82 private static final int TAB_SWITCHER_MODE_ENTER_ANIMATION_DURATION_MS = 200
; |
| 83 private static final int TAB_SWITCHER_MODE_EXIT_NORMAL_ANIMATION_DURATION_MS
= 200; |
| 84 private static final int TAB_SWITCHER_MODE_EXIT_FADE_ANIMATION_DURATION_MS =
100; |
| 85 private static final int TAB_SWITCHER_MODE_POST_EXIT_ANIMATION_DURATION_MS =
100; |
| 86 |
| 87 private static final float UNINITIALIZED_PERCENT = -1f; |
| 88 |
| 89 private static final int BRAND_COLOR_TRANSITION_DURATION_MS = 250; |
| 90 |
| 91 static final int LOCATION_BAR_TRANSPARENT_BACKGROUND_ALPHA = 51; |
| 92 |
| 93 private LocationBarPhone mPhoneLocationBar; |
| 94 |
| 95 private View mToolbarButtonsContainer; |
| 96 private ImageView mToggleTabStackButton; |
| 97 private NewTabButton mNewTabButton; |
| 98 private TintedImageButton mHomeButton; |
| 99 private TextView mUrlBar; |
| 100 private UrlContainer mUrlContainer; |
| 101 private View mUrlActionsContainer; |
| 102 private ImageView mToolbarShadow; |
| 103 |
| 104 private ObjectAnimator mTabSwitcherModeAnimation; |
| 105 private ObjectAnimator mDelayedTabSwitcherModeAnimation; |
| 106 |
| 107 private final List<View> mTabSwitcherModeViews = new ArrayList<View>(); |
| 108 private final Set<View> mBrowsingModeViews = new HashSet<View>(); |
| 109 private boolean mInTabSwitcherMode; |
| 110 // This determines whether or not the toolbar draws as expected (false) or w
hether it always |
| 111 // draws as if it's showing the non-tabswitcher, non-animating toolbar. This
is used in grabbing |
| 112 // a bitmap to use as a texture representation of this view. |
| 113 private boolean mTextureCaptureMode; |
| 114 private boolean mAnimateNormalToolbar; |
| 115 private boolean mDelayingTabSwitcherAnimation; |
| 116 |
| 117 private ColorDrawable mTabSwitcherAnimationBgOverlay; |
| 118 private TabSwitcherDrawable mTabSwitcherAnimationTabStackDrawable; |
| 119 private Drawable mTabSwitcherAnimationMenuDrawable; |
| 120 // Value that determines the amount of transition from the normal toolbar mo
de to TabSwitcher |
| 121 // mode. 0 = entirely in normal mode and 1.0 = entirely in TabSwitcher mode
. In between values |
| 122 // can be used for animating between the two view modes. |
| 123 private float mTabSwitcherModePercent = 0; |
| 124 private boolean mUIAnimatingTabSwitcherTransition; |
| 125 |
| 126 // Used to clip the toolbar during the fade transition into and out of TabSw
itcher mode. Only |
| 127 // used when |mAnimateNormalToolbar| is false. |
| 128 private Rect mClipRect; |
| 129 |
| 130 private OnClickListener mTabSwitcherListener; |
| 131 private OnClickListener mNewTabListener; |
| 132 |
| 133 private boolean mUrlFocusChangeInProgress; |
| 134 /** 1.0 is 100% focused, 0 is completely unfocused */ |
| 135 private float mUrlFocusChangePercent; |
| 136 /** 1.0 is 100% expanded to full width, 0 is original collapsed size. */ |
| 137 private float mUrlExpansionPercent; |
| 138 private AnimatorSet mUrlFocusLayoutAnimator; |
| 139 private boolean mDisableLocationBarRelayout; |
| 140 private boolean mLayoutLocationBarInFocusedMode; |
| 141 private int mUnfocusedLocationBarLayoutWidth; |
| 142 private int mUnfocusedLocationBarLayoutLeft; |
| 143 private boolean mUnfocusedLocationBarUsesTransparentBg; |
| 144 |
| 145 private int mUrlBackgroundAlpha = 255; |
| 146 private float mNtpSearchBoxScrollPercent = UNINITIALIZED_PERCENT; |
| 147 private ColorDrawable mToolbarBackground; |
| 148 private Drawable mLocationBarBackground; |
| 149 private boolean mForceDrawLocationBarBackground; |
| 150 private TabSwitcherDrawable mTabSwitcherButtonDrawable; |
| 151 private TabSwitcherDrawable mTabSwitcherButtonDrawableLight; |
| 152 |
| 153 private final Rect mUrlViewportBounds = new Rect(); |
| 154 private final Rect mUrlBackgroundPadding = new Rect(); |
| 155 private final Rect mBackgroundOverlayBounds = new Rect(); |
| 156 private final Rect mLocationBarBackgroundOffset = new Rect(); |
| 157 |
| 158 private final Rect mNtpSearchBoxOriginalBounds = new Rect(); |
| 159 private final Rect mNtpSearchBoxTransformedBounds = new Rect(); |
| 160 |
| 161 private final int mLocationBarInsets; |
| 162 private final int mToolbarSidePadding; |
| 163 |
| 164 private ValueAnimator mBrandColorTransitionAnimation; |
| 165 private boolean mBrandColorTransitionActive; |
| 166 |
| 167 /** |
| 168 * Used to specify the visual state of the toolbar. |
| 169 */ |
| 170 private enum VisualState { |
| 171 TAB_SWITCHER_INCOGNITO, |
| 172 TAB_SWITCHER_NORMAL, |
| 173 NORMAL, |
| 174 INCOGNITO, |
| 175 BRAND_COLOR, |
| 176 NEW_TAB_NORMAL |
| 177 } |
| 178 |
| 179 private VisualState mVisualState = VisualState.NORMAL; |
| 180 private VisualState mOverlayDrawablesVisualState; |
| 181 private boolean mUseLightToolbarDrawables; |
| 182 |
| 183 private NewTabPage mVisibleNewTabPage; |
| 184 private float mPreTextureCaptureAlpha = 1f; |
| 185 private boolean mIsOverlayTabStackDrawableLight; |
| 186 |
| 187 // The following are some properties used during animation. We use explicit
property classes |
| 188 // to avoid the cost of reflection for each animation setup. |
| 189 |
| 190 private final Property<ToolbarPhone, Float> mUrlFocusChangePercentProperty = |
| 191 new Property<ToolbarPhone, Float>(Float.class, "") { |
| 192 @Override |
| 193 public Float get(ToolbarPhone object) { |
| 194 return object.mUrlFocusChangePercent; |
| 195 } |
| 196 |
| 197 @Override |
| 198 public void set(ToolbarPhone object, Float value) { |
| 199 setUrlFocusChangePercent(value); |
| 200 } |
| 201 }; |
| 202 |
| 203 private final Property<ToolbarPhone, Float> mTabSwitcherModePercentProperty
= |
| 204 new Property<ToolbarPhone, Float>(Float.class, "") { |
| 205 @Override |
| 206 public Float get(ToolbarPhone object) { |
| 207 return object.mTabSwitcherModePercent; |
| 208 } |
| 209 |
| 210 @Override |
| 211 public void set(ToolbarPhone object, Float value) { |
| 212 object.mTabSwitcherModePercent = value; |
| 213 triggerPaintInvalidate(ToolbarPhone.this); |
| 214 } |
| 215 }; |
| 216 |
| 217 /** |
| 218 * Constructs a ToolbarPhone object. |
| 219 * @param context The Context in which this View object is created. |
| 220 * @param attrs The AttributeSet that was specified with this View. |
| 221 */ |
| 222 public ToolbarPhone(Context context, AttributeSet attrs) { |
| 223 super(context, attrs); |
| 224 mToolbarSidePadding = getResources().getDimensionPixelOffset( |
| 225 R.dimen.toolbar_edge_padding); |
| 226 // Insets used for the PhoneLocatioBar background drawable. |
| 227 mLocationBarInsets = getResources().getDimensionPixelSize(R.dimen.locati
on_bar_margin_top) |
| 228 + getResources().getDimensionPixelSize(R.dimen.location_bar_marg
in_bottom); |
| 229 } |
| 230 |
| 231 @Override |
| 232 public void onFinishInflate() { |
| 233 super.onFinishInflate(); |
| 234 Context context = getContext(); |
| 235 |
| 236 mPhoneLocationBar = (LocationBarPhone) findViewById(R.id.location_bar); |
| 237 |
| 238 mToolbarButtonsContainer = findViewById(R.id.toolbar_buttons); |
| 239 |
| 240 mToggleTabStackButton = (ImageView) findViewById(R.id.tab_switcher_butto
n); |
| 241 mToggleTabStackButton.setClickable(false); |
| 242 |
| 243 Resources resources = getResources(); |
| 244 mTabSwitcherButtonDrawable = |
| 245 TabSwitcherDrawable.createTabSwitcherDrawable(resources, false); |
| 246 mTabSwitcherButtonDrawableLight = |
| 247 TabSwitcherDrawable.createTabSwitcherDrawable(resources, true); |
| 248 |
| 249 mToggleTabStackButton.setVisibility(FeatureUtilities.isDocumentMode(getC
ontext()) |
| 250 ? GONE : VISIBLE); |
| 251 mToggleTabStackButton.setImageDrawable(mTabSwitcherButtonDrawable); |
| 252 |
| 253 mNewTabButton = (NewTabButton) findViewById(R.id.new_tab_button); |
| 254 mHomeButton = (TintedImageButton) findViewById(R.id.home_button); |
| 255 |
| 256 mUrlBar = (TextView) findViewById(R.id.url_bar); |
| 257 mUrlContainer = (UrlContainer) findViewById(R.id.url_container); |
| 258 |
| 259 mUrlActionsContainer = findViewById(R.id.url_action_container); |
| 260 |
| 261 mTabSwitcherModeViews.add(mNewTabButton); |
| 262 mBrowsingModeViews.add(mPhoneLocationBar); |
| 263 |
| 264 mToolbarBackground = new ColorDrawable(getToolbarColorForVisualState(Vis
ualState.NORMAL)); |
| 265 |
| 266 mTabSwitcherAnimationBgOverlay = |
| 267 new ColorDrawable(getToolbarColorForVisualState(VisualState.NORM
AL)); |
| 268 |
| 269 mLocationBarBackground = |
| 270 ApiCompatibilityUtils.getDrawable(getResources(), R.drawable.ins
et_textbox); |
| 271 mLocationBarBackground.getPadding(mUrlBackgroundPadding); |
| 272 mPhoneLocationBar.setPadding( |
| 273 mUrlBackgroundPadding.left, mUrlBackgroundPadding.top, |
| 274 mUrlBackgroundPadding.right, mUrlBackgroundPadding.bottom); |
| 275 |
| 276 setLayoutTransition(null); |
| 277 |
| 278 mMenuButton.setVisibility(shouldShowMenuButton() ? View.VISIBLE : View.G
ONE); |
| 279 |
| 280 // Ensure that the new tab button will not draw over the toolbar buttons
if the translated |
| 281 // string is long. Set a margin to the size of the toolbar button conta
iner for the new |
| 282 // tab button. |
| 283 WindowManager wm = (WindowManager) context.getSystemService(Context.WIND
OW_SERVICE); |
| 284 Point screenSize = new Point(); |
| 285 wm.getDefaultDisplay().getSize(screenSize); |
| 286 |
| 287 mToolbarButtonsContainer.measure( |
| 288 MeasureSpec.makeMeasureSpec(screenSize.x, MeasureSpec.AT_MOST), |
| 289 MeasureSpec.makeMeasureSpec(screenSize.y, MeasureSpec.AT_MOST)); |
| 290 ApiCompatibilityUtils.setMarginEnd(getFrameLayoutParams(mNewTabButton), |
| 291 mToolbarButtonsContainer.getMeasuredWidth()); |
| 292 |
| 293 setWillNotDraw(false); |
| 294 } |
| 295 |
| 296 /** |
| 297 * Sets up click and key listeners once we have native library available to
handle clicks. |
| 298 */ |
| 299 @Override |
| 300 public void onNativeLibraryReady() { |
| 301 super.onNativeLibraryReady(); |
| 302 getLocationBar().onNativeLibraryReady(); |
| 303 mToggleTabStackButton.setOnClickListener(this); |
| 304 mToggleTabStackButton.setOnLongClickListener(this); |
| 305 mToggleTabStackButton.setOnKeyListener(new KeyboardNavigationListener()
{ |
| 306 @Override |
| 307 public View getNextFocusForward() { |
| 308 if (mMenuButton != null && mMenuButton.isShown()) { |
| 309 return mMenuButton; |
| 310 } else { |
| 311 return getCurrentTabView(); |
| 312 } |
| 313 } |
| 314 |
| 315 @Override |
| 316 public View getNextFocusBackward() { |
| 317 return findViewById(R.id.url_bar); |
| 318 } |
| 319 }); |
| 320 mNewTabButton.setOnClickListener(this); |
| 321 mHomeButton.setOnClickListener(this); |
| 322 |
| 323 mMenuButton.setOnKeyListener(new KeyboardNavigationListener() { |
| 324 @Override |
| 325 public View getNextFocusForward() { |
| 326 return getCurrentTabView(); |
| 327 } |
| 328 |
| 329 @Override |
| 330 public View getNextFocusBackward() { |
| 331 return mToggleTabStackButton; |
| 332 } |
| 333 |
| 334 @Override |
| 335 protected boolean handleEnterKeyPress() { |
| 336 return getMenuButtonHelper().onEnterKeyPress(mMenuButton); |
| 337 } |
| 338 }); |
| 339 onHomeButtonUpdate(HomepageManager.isHomepageEnabled(getContext())); |
| 340 |
| 341 updateVisualsForToolbarState(mInTabSwitcherMode); |
| 342 } |
| 343 |
| 344 @Override |
| 345 public boolean onInterceptTouchEvent(MotionEvent ev) { |
| 346 // If the NTP is partially scrolled, prevent all touch events to the chi
ld views. This |
| 347 // is to not allow a secondary touch event to trigger entering the tab s
witcher, which |
| 348 // can lead to really odd snapshots and transitions to the switcher. |
| 349 if (mNtpSearchBoxScrollPercent != 0f |
| 350 && mNtpSearchBoxScrollPercent != 1f |
| 351 && mNtpSearchBoxScrollPercent != UNINITIALIZED_PERCENT) { |
| 352 return true; |
| 353 } |
| 354 return super.onInterceptTouchEvent(ev); |
| 355 } |
| 356 |
| 357 @Override |
| 358 public void onClick(View v) { |
| 359 if (mToggleTabStackButton == v) { |
| 360 // The button is clickable before the native library is loaded |
| 361 // and the listener is setup. |
| 362 if (mToggleTabStackButton != null && mToggleTabStackButton.isClickab
le() |
| 363 && mTabSwitcherListener != null) { |
| 364 mTabSwitcherListener.onClick(mToggleTabStackButton); |
| 365 RecordUserAction.record("MobileToolbarShowStackView"); |
| 366 } |
| 367 } else if (mNewTabButton == v) { |
| 368 v.setEnabled(false); |
| 369 |
| 370 if (mNewTabListener != null) { |
| 371 mNewTabListener.onClick(v); |
| 372 RecordUserAction.record("MobileToolbarStackViewNewTab"); |
| 373 RecordUserAction.record("MobileNewTabOpened"); |
| 374 // TODO(kkimlabs): Record UMA action for homepage button. |
| 375 } |
| 376 } else if (mHomeButton == v) { |
| 377 openHomepage(); |
| 378 } |
| 379 } |
| 380 |
| 381 @Override |
| 382 public boolean onLongClick(View v) { |
| 383 int stringResourceId = -1; |
| 384 if (v == mToggleTabStackButton) { |
| 385 stringResourceId = R.string.open_tabs; |
| 386 } |
| 387 if (stringResourceId != -1) { |
| 388 Context ctx = getContext(); |
| 389 // Display the tooltip for the view being long clicked. |
| 390 final int screenWidth = getResources().getDisplayMetrics().widthPixe
ls; |
| 391 final int[] screenPos = new int[2]; |
| 392 v.getLocationOnScreen(screenPos); |
| 393 final int width = v.getWidth(); |
| 394 |
| 395 Toast toast = Toast.makeText( |
| 396 ctx, getResources().getString(stringResourceId), Toast.LENGT
H_SHORT); |
| 397 toast.setGravity( |
| 398 Gravity.TOP | Gravity.END, |
| 399 screenWidth - screenPos[0] - width / 2, |
| 400 getHeight()); |
| 401 toast.show(); |
| 402 return true; |
| 403 } |
| 404 return false; |
| 405 } |
| 406 |
| 407 @Override |
| 408 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { |
| 409 if (!mDisableLocationBarRelayout) { |
| 410 super.onMeasure(widthMeasureSpec, heightMeasureSpec); |
| 411 |
| 412 boolean changed = layoutLocationBar(MeasureSpec.getSize(widthMeasure
Spec)); |
| 413 setUrlFocusChangePercent(mUrlFocusChangePercent); |
| 414 if (!changed) return; |
| 415 } else { |
| 416 updateUnfocusedLocationBarLayoutParams(); |
| 417 } |
| 418 |
| 419 super.onMeasure(widthMeasureSpec, heightMeasureSpec); |
| 420 } |
| 421 |
| 422 private void updateUnfocusedLocationBarLayoutParams() { |
| 423 boolean hasVisibleViewPriorToUrlBar = false; |
| 424 for (int i = 0; i < mPhoneLocationBar.getChildCount(); i++) { |
| 425 View child = mPhoneLocationBar.getChildAt(i); |
| 426 if (child == mUrlContainer) break; |
| 427 if (child.getVisibility() != GONE) { |
| 428 hasVisibleViewPriorToUrlBar = true; |
| 429 break; |
| 430 } |
| 431 } |
| 432 |
| 433 int leftViewBounds = getViewBoundsLeftOfLocationBar(); |
| 434 if (!hasVisibleViewPriorToUrlBar) leftViewBounds += mToolbarSidePadding; |
| 435 int rightViewBounds = getViewBoundsRightOfLocationBar(); |
| 436 |
| 437 if (!mPhoneLocationBar.hasVisibleViewsAfterUrlBarWhenUnfocused()) { |
| 438 // Add spacing between the end of the URL and the edge of the omnibo
x drawable. |
| 439 // This only applies if there is no end aligned view that should be
visible |
| 440 // while the omnibox is unfocused. |
| 441 if (ApiCompatibilityUtils.isLayoutRtl(mPhoneLocationBar)) { |
| 442 leftViewBounds += mToolbarSidePadding; |
| 443 } else { |
| 444 rightViewBounds -= mToolbarSidePadding; |
| 445 } |
| 446 } |
| 447 |
| 448 mUnfocusedLocationBarLayoutWidth = rightViewBounds - leftViewBounds; |
| 449 mUnfocusedLocationBarLayoutLeft = leftViewBounds; |
| 450 } |
| 451 |
| 452 /** |
| 453 * @return The background drawable for the fullscreen overlay. |
| 454 */ |
| 455 @VisibleForTesting |
| 456 ColorDrawable getOverlayDrawable() { |
| 457 return mTabSwitcherAnimationBgOverlay; |
| 458 } |
| 459 |
| 460 /** |
| 461 * @return The background drawable for the toolbar view. |
| 462 */ |
| 463 @VisibleForTesting |
| 464 ColorDrawable getBackgroundDrawable() { |
| 465 return mToolbarBackground; |
| 466 } |
| 467 |
| 468 @SuppressLint("RtlHardcoded") |
| 469 private boolean layoutLocationBar(int containerWidth) { |
| 470 // Note that Toolbar's direction depends on system layout direction whil
e |
| 471 // LocationBar's direction depends on its text inside. |
| 472 FrameLayout.LayoutParams locationBarLayoutParams = |
| 473 getFrameLayoutParams(getLocationBar().getContainerView()); |
| 474 |
| 475 // Chrome prevents layout_gravity="left" from being defined in XML, but
it simplifies |
| 476 // the logic, so it is manually specified here. |
| 477 locationBarLayoutParams.gravity = Gravity.TOP | Gravity.LEFT; |
| 478 |
| 479 int width = 0; |
| 480 int leftMargin = 0; |
| 481 |
| 482 // Always update the unfocused layout params regardless of whether we ar
e using |
| 483 // those in this current layout pass as they are needed for animations. |
| 484 updateUnfocusedLocationBarLayoutParams(); |
| 485 |
| 486 if (mLayoutLocationBarInFocusedMode || mVisualState == VisualState.NEW_T
AB_NORMAL) { |
| 487 int priorVisibleWidth = 0; |
| 488 for (int i = 0; i < mPhoneLocationBar.getChildCount(); i++) { |
| 489 View child = mPhoneLocationBar.getChildAt(i); |
| 490 if (child == mPhoneLocationBar.getFirstViewVisibleWhenFocused())
break; |
| 491 if (child.getVisibility() == GONE) continue; |
| 492 priorVisibleWidth += child.getMeasuredWidth(); |
| 493 } |
| 494 |
| 495 width = containerWidth - (2 * mToolbarSidePadding) + priorVisibleWid
th; |
| 496 if (ApiCompatibilityUtils.isLayoutRtl(mPhoneLocationBar)) { |
| 497 leftMargin = mToolbarSidePadding; |
| 498 } else { |
| 499 leftMargin = -priorVisibleWidth + mToolbarSidePadding; |
| 500 } |
| 501 } else { |
| 502 width = mUnfocusedLocationBarLayoutWidth; |
| 503 leftMargin = mUnfocusedLocationBarLayoutLeft; |
| 504 } |
| 505 |
| 506 boolean changed = false; |
| 507 changed |= (width != locationBarLayoutParams.width); |
| 508 locationBarLayoutParams.width = width; |
| 509 |
| 510 changed |= (leftMargin != locationBarLayoutParams.leftMargin); |
| 511 locationBarLayoutParams.leftMargin = leftMargin; |
| 512 |
| 513 return changed; |
| 514 } |
| 515 |
| 516 private int getViewBoundsLeftOfLocationBar() { |
| 517 // Uses getMeasuredWidth()s instead of getLeft() because this is called
in onMeasure |
| 518 // and the layout values have not yet been set. |
| 519 if (mVisualState == VisualState.NEW_TAB_NORMAL) { |
| 520 return 0; |
| 521 } else if (ApiCompatibilityUtils.isLayoutRtl(this)) { |
| 522 return Math.max( |
| 523 mToolbarSidePadding, mToolbarButtonsContainer.getMeasuredWid
th()); |
| 524 } else { |
| 525 return mHomeButton.getVisibility() != GONE |
| 526 ? mHomeButton.getMeasuredWidth() : mToolbarSidePadding; |
| 527 } |
| 528 } |
| 529 |
| 530 private int getViewBoundsRightOfLocationBar() { |
| 531 // Uses getMeasuredWidth()s instead of getRight() because this is called
in onMeasure |
| 532 // and the layout values have not yet been set. |
| 533 if (mVisualState == VisualState.NEW_TAB_NORMAL) { |
| 534 return getMeasuredWidth(); |
| 535 } else if (ApiCompatibilityUtils.isLayoutRtl(this)) { |
| 536 return getMeasuredWidth() - (mHomeButton.getVisibility() != GONE |
| 537 ? mHomeButton.getMeasuredWidth() : mToolbarSidePadding); |
| 538 } else { |
| 539 int margin = Math.max( |
| 540 mToolbarSidePadding, mToolbarButtonsContainer.getMeasuredWid
th()); |
| 541 return getMeasuredWidth() - margin; |
| 542 } |
| 543 } |
| 544 |
| 545 private void updateToolbarBackground(int color) { |
| 546 mToolbarBackground.setColor(color); |
| 547 invalidate(); |
| 548 } |
| 549 |
| 550 private void updateToolbarBackground(VisualState visualState) { |
| 551 updateToolbarBackground(getToolbarColorForVisualState(visualState)); |
| 552 } |
| 553 |
| 554 private int getToolbarColorForVisualState(final VisualState visualState) { |
| 555 Resources res = getResources(); |
| 556 switch (visualState) { |
| 557 case NEW_TAB_NORMAL: |
| 558 return Color.TRANSPARENT; |
| 559 case NORMAL : |
| 560 return res.getColor(R.color.default_primary_color); |
| 561 case INCOGNITO: |
| 562 return res.getColor(R.color.incognito_primary_color); |
| 563 case BRAND_COLOR: |
| 564 return getToolbarDataProvider().getPrimaryColor(); |
| 565 case TAB_SWITCHER_NORMAL: |
| 566 case TAB_SWITCHER_INCOGNITO: |
| 567 return res.getColor(R.color.tab_switcher_background); |
| 568 default: |
| 569 assert false; |
| 570 return res.getColor(R.color.default_primary_color); |
| 571 } |
| 572 } |
| 573 |
| 574 @Override |
| 575 protected void dispatchDraw(Canvas canvas) { |
| 576 if (!mTextureCaptureMode && mToolbarBackground.getColor() != Color.TRANS
PARENT) { |
| 577 // Update to compensate for orientation changes. |
| 578 mToolbarBackground.setBounds(0, 0, getWidth(), getHeight()); |
| 579 mToolbarBackground.draw(canvas); |
| 580 } |
| 581 |
| 582 if (mLocationBarBackground != null |
| 583 && (mPhoneLocationBar.getVisibility() == VISIBLE || mTextureCapt
ureMode)) { |
| 584 // Calculate the visible boundaries of the left and right most child
views |
| 585 // of the location bar. |
| 586 int leftViewPosition = getViewBoundsLeftOfLocationBar(); |
| 587 int rightViewPosition = getViewBoundsRightOfLocationBar(); |
| 588 |
| 589 leftViewPosition -= mUrlBackgroundPadding.left; |
| 590 if (mUrlExpansionPercent != 0f) { |
| 591 leftViewPosition *= (1f - mUrlExpansionPercent); |
| 592 leftViewPosition -= mUrlBackgroundPadding.left * mUrlExpansionPe
rcent; |
| 593 } |
| 594 |
| 595 rightViewPosition += mUrlBackgroundPadding.right; |
| 596 if (mUrlExpansionPercent != 0f) { |
| 597 rightViewPosition += ((getWidth() - rightViewPosition) * mUrlExp
ansionPercent); |
| 598 rightViewPosition += mUrlBackgroundPadding.right * mUrlExpansion
Percent; |
| 599 } |
| 600 |
| 601 // The bounds are set by the following: |
| 602 // - The left most visible location bar child view. |
| 603 // - The top of the viewport is aligned with the top of the location
bar. |
| 604 // - The right most visible location bar child view. |
| 605 // - The bottom of the viewport is aligned with the bottom of the lo
cation bar. |
| 606 // Additional padding can be applied for use during animations. |
| 607 mUrlViewportBounds.set( |
| 608 leftViewPosition, |
| 609 0, |
| 610 rightViewPosition, |
| 611 (int) (mPhoneLocationBar.getMeasuredHeight() |
| 612 + (getHeight() - mPhoneLocationBar.getMeasuredHeight
() |
| 613 + mUrlBackgroundPadding.bottom + mUrlBackgro
undPadding.top) |
| 614 * mUrlExpansionPercent)); |
| 615 mUrlViewportBounds.offset(0, (int) (mPhoneLocationBar.getY() |
| 616 - (mUrlBackgroundPadding.top * mUrlExpansionPercent))); |
| 617 } |
| 618 |
| 619 if (mTextureCaptureMode) { |
| 620 drawTabSwitcherAnimationOverlay(canvas, 0.f); |
| 621 } else { |
| 622 boolean tabSwitcherAnimationFinished = false; |
| 623 if (mTabSwitcherModeAnimation != null) { |
| 624 tabSwitcherAnimationFinished = !mTabSwitcherModeAnimation.isRunn
ing(); |
| 625 |
| 626 // Perform the fade logic before super.dispatchDraw(canvas) so t
hat we can properly |
| 627 // set the values before the draw happens. |
| 628 if (!mAnimateNormalToolbar) { |
| 629 drawTabSwitcherFadeAnimation( |
| 630 tabSwitcherAnimationFinished, mTabSwitcherModePercen
t); |
| 631 } |
| 632 } |
| 633 |
| 634 super.dispatchDraw(canvas); |
| 635 |
| 636 if (mTabSwitcherModeAnimation != null) { |
| 637 // Perform the overlay logic after super.dispatchDraw(canvas) as
we need to draw on |
| 638 // top of the current views. |
| 639 if (mAnimateNormalToolbar) { |
| 640 drawTabSwitcherAnimationOverlay(canvas, mTabSwitcherModePerc
ent); |
| 641 } |
| 642 |
| 643 // Clear the animation. |
| 644 if (tabSwitcherAnimationFinished) mTabSwitcherModeAnimation = nu
ll; |
| 645 } |
| 646 } |
| 647 } |
| 648 |
| 649 // NewTabPage.OnSearchBoxScrollListener |
| 650 @Override |
| 651 public void onScrollChanged(float scrollPercentage) { |
| 652 if (scrollPercentage == mNtpSearchBoxScrollPercent) return; |
| 653 |
| 654 mNtpSearchBoxScrollPercent = scrollPercentage; |
| 655 updateUrlExpansionPercent(); |
| 656 updateUrlExpansionAnimation(); |
| 657 } |
| 658 |
| 659 /** |
| 660 * Updates percentage of current the URL focus change animation. |
| 661 * @param percent 1.0 is 100% focused, 0 is completely unfocused. |
| 662 */ |
| 663 private void setUrlFocusChangePercent(float percent) { |
| 664 mUrlFocusChangePercent = percent; |
| 665 updateUrlExpansionPercent(); |
| 666 updateUrlExpansionAnimation(); |
| 667 } |
| 668 |
| 669 private void updateUrlExpansionPercent() { |
| 670 mUrlExpansionPercent = Math.max(mNtpSearchBoxScrollPercent, mUrlFocusCha
ngePercent); |
| 671 assert mUrlExpansionPercent >= 0; |
| 672 assert mUrlExpansionPercent <= 1; |
| 673 } |
| 674 |
| 675 private void updateUrlExpansionAnimation() { |
| 676 mLocationBarBackgroundOffset.setEmpty(); |
| 677 |
| 678 FrameLayout.LayoutParams locationBarLayoutParams = |
| 679 getFrameLayoutParams(mPhoneLocationBar); |
| 680 int currentLeftMargin = locationBarLayoutParams.leftMargin; |
| 681 int currentWidth = locationBarLayoutParams.width; |
| 682 |
| 683 float inversePercent = 1f - mUrlExpansionPercent; |
| 684 boolean isLocationBarRtl = ApiCompatibilityUtils.isLayoutRtl(mPhoneLocat
ionBar); |
| 685 if (ApiCompatibilityUtils.isLayoutRtl(mPhoneLocationBar)) { |
| 686 mPhoneLocationBar.setTranslationX( |
| 687 ((mUnfocusedLocationBarLayoutLeft + mUnfocusedLocationBarLay
outWidth) |
| 688 - (currentLeftMargin + currentWidth)) * inversePerce
nt); |
| 689 } else { |
| 690 mPhoneLocationBar.setTranslationX( |
| 691 (mUnfocusedLocationBarLayoutLeft - currentLeftMargin) * inve
rsePercent); |
| 692 mUrlActionsContainer.setTranslationX(-mPhoneLocationBar.getTranslati
onX()); |
| 693 } |
| 694 |
| 695 // Negate the location bar translation to keep the URL action container
in the same |
| 696 // place during the focus expansion. The check for RTL parity is requir
ed because |
| 697 // if they do not match then the action container will overlap the URL i
f we do not |
| 698 // allow it to be pushed off. |
| 699 if (isLocationBarRtl == ApiCompatibilityUtils.isLayoutRtl(this)) { |
| 700 mUrlActionsContainer.setTranslationX(-mPhoneLocationBar.getTranslati
onX()); |
| 701 } |
| 702 |
| 703 mPhoneLocationBar.setUrlFocusChangePercent(mUrlExpansionPercent); |
| 704 |
| 705 // Ensure the buttons are invisible after focusing the omnibox to preven
t them from |
| 706 // accepting click events. |
| 707 int toolbarButtonVisibility = mUrlExpansionPercent == 1f ? INVISIBLE : V
ISIBLE; |
| 708 mToolbarButtonsContainer.setVisibility(toolbarButtonVisibility); |
| 709 if (mHomeButton.getVisibility() != GONE) { |
| 710 mHomeButton.setVisibility(toolbarButtonVisibility); |
| 711 } |
| 712 |
| 713 // Force an invalidation of the location bar to properly handle the clip
ping of the URL |
| 714 // bar text as a result of the url action container translations. |
| 715 mPhoneLocationBar.invalidate(); |
| 716 invalidate(); |
| 717 |
| 718 Tab currentTab = getToolbarDataProvider().getTab(); |
| 719 if (currentTab == null) return; |
| 720 |
| 721 NewTabPage ntp = getToolbarDataProvider().getNewTabPageForCurrentTab(); |
| 722 // Explicitly use the focus change percentage here because it applies sc
roll compensation |
| 723 // that only applies during focus animations. |
| 724 if (ntp != null) ntp.setUrlFocusChangeAnimationPercent(mUrlFocusChangePe
rcent); |
| 725 |
| 726 if (!isLocationBarShownInNTP()) { |
| 727 // Reset these values in case we transitioned to a different page du
ring the |
| 728 // transition. |
| 729 resetNtpAnimationValues(); |
| 730 return; |
| 731 } |
| 732 |
| 733 updateNtpTransitionAnimation(ntp); |
| 734 } |
| 735 |
| 736 private void resetNtpAnimationValues() { |
| 737 mLocationBarBackgroundOffset.setEmpty(); |
| 738 mPhoneLocationBar.setTranslationY(0); |
| 739 if (!mUrlFocusChangeInProgress) { |
| 740 mToolbarButtonsContainer.setTranslationY(0); |
| 741 mHomeButton.setTranslationY(0); |
| 742 } |
| 743 mToolbarShadow.setAlpha(1f); |
| 744 mPhoneLocationBar.setAlpha(1); |
| 745 mForceDrawLocationBarBackground = false; |
| 746 mUrlBackgroundAlpha = isIncognito() |
| 747 || (mUnfocusedLocationBarUsesTransparentBg |
| 748 && !mUrlFocusChangeInProgress |
| 749 && !mPhoneLocationBar.hasFocus()) |
| 750 ? LOCATION_BAR_TRANSPARENT_BACKGROUND_ALPHA : 255; |
| 751 setAncestorsShouldClipChildren(true); |
| 752 mNtpSearchBoxScrollPercent = UNINITIALIZED_PERCENT; |
| 753 } |
| 754 |
| 755 private void updateNtpTransitionAnimation(NewTabPage ntp) { |
| 756 if (mInTabSwitcherMode) return; |
| 757 |
| 758 setAncestorsShouldClipChildren(mUrlExpansionPercent == 0f); |
| 759 mToolbarShadow.setAlpha(0f); |
| 760 |
| 761 float growthPercent = 0f; |
| 762 if (mUrlExpansionPercent == 0f || mUrlExpansionPercent == 1f) { |
| 763 growthPercent = 1f - mUrlExpansionPercent; |
| 764 } else { |
| 765 // During the transition from search box to omnibox, keep the omnibo
x drawing |
| 766 // at the same size of the search box for first 40% of the scroll tr
ansition. |
| 767 growthPercent = mUrlExpansionPercent <= 0.4f |
| 768 ? 1f : Math.min(1f, (1f - mUrlExpansionPercent) * 1.66667f); |
| 769 } |
| 770 |
| 771 int paddingTop = mPhoneLocationBar.getPaddingTop(); |
| 772 int paddingBottom = mPhoneLocationBar.getPaddingBottom(); |
| 773 |
| 774 ntp.getSearchBoxBounds(mNtpSearchBoxOriginalBounds, mNtpSearchBoxTransfo
rmedBounds); |
| 775 float halfHeightDifference = (mNtpSearchBoxTransformedBounds.height() |
| 776 - (mPhoneLocationBar.getMeasuredHeight() - paddingTop - paddingB
ottom |
| 777 + mLocationBarInsets)) / 2f; |
| 778 mPhoneLocationBar.setTranslationY(growthPercent == 0f ? 0 : Math.max(0, |
| 779 (mNtpSearchBoxTransformedBounds.top - mPhoneLocationBar.getTop() |
| 780 + halfHeightDifference))); |
| 781 if (!mUrlFocusChangeInProgress) { |
| 782 float searchBoxTranslationY = |
| 783 mNtpSearchBoxTransformedBounds.top - mNtpSearchBoxOriginalBo
unds.top; |
| 784 mToolbarButtonsContainer.setTranslationY(searchBoxTranslationY); |
| 785 mHomeButton.setTranslationY(searchBoxTranslationY); |
| 786 } |
| 787 |
| 788 mLocationBarBackgroundOffset.set( |
| 789 (int) ((mNtpSearchBoxTransformedBounds.left - mUrlViewportBounds
.left |
| 790 - mPhoneLocationBar.getPaddingLeft()) * growthPercent), |
| 791 (int) ((-halfHeightDifference - paddingTop) * growthPercent), |
| 792 (int) ((mNtpSearchBoxTransformedBounds.right - mUrlViewportBound
s.right |
| 793 + mPhoneLocationBar.getPaddingRight()) * growthPercent), |
| 794 (int) ((halfHeightDifference - paddingBottom + mLocationBarInset
s) |
| 795 * growthPercent)); |
| 796 |
| 797 // The transparency of the location bar is dependent on how different it
s size is |
| 798 // from the final value. This is based on how much growth is applied be
tween the |
| 799 // desired size of the location bar to it's drawn size. The location ba
r then only |
| 800 // starts becoming opaque once the growth is at least half done. |
| 801 if (growthPercent >= 0.5f) { |
| 802 mPhoneLocationBar.setAlpha(0); |
| 803 } else { |
| 804 mPhoneLocationBar.setAlpha(1f - growthPercent * 2); |
| 805 } |
| 806 |
| 807 // Go from a transparent url background to a fully opaque one in the fir
st 40% of the |
| 808 // scroll transition. |
| 809 mUrlBackgroundAlpha = |
| 810 mUrlExpansionPercent >= 0.4f ? 255 : (int) ((mUrlExpansionPercen
t * 2.5f) * 255); |
| 811 if (mUrlExpansionPercent == 1f) mUrlBackgroundAlpha = 255; |
| 812 mForceDrawLocationBarBackground = mUrlExpansionPercent != 0f; |
| 813 } |
| 814 |
| 815 private void setAncestorsShouldClipChildren(boolean clip) { |
| 816 if (!isLocationBarShownInNTP()) return; |
| 817 ViewGroup parent = this; |
| 818 while (parent != null) { |
| 819 parent.setClipChildren(clip); |
| 820 if (!(parent.getParent() instanceof ViewGroup)) break; |
| 821 if (parent.getId() == android.R.id.content) break; |
| 822 parent = (ViewGroup) parent.getParent(); |
| 823 } |
| 824 } |
| 825 |
| 826 private void drawTabSwitcherFadeAnimation(boolean animationFinished, float p
rogress) { |
| 827 setAlpha(progress); |
| 828 if (animationFinished) { |
| 829 mClipRect = null; |
| 830 } else if (mClipRect == null) { |
| 831 mClipRect = new Rect(); |
| 832 } |
| 833 if (mClipRect != null) mClipRect.set(0, 0, getWidth(), (int) (getHeight(
) * progress)); |
| 834 } |
| 835 |
| 836 /** |
| 837 * When entering and exiting the TabSwitcher mode, we fade out or fade in th
e browsing |
| 838 * mode of the toolbar on top of the TabSwitcher mode version of it. We do
this by |
| 839 * drawing all of the browsing mode views on top of the android view. |
| 840 */ |
| 841 private void drawTabSwitcherAnimationOverlay(Canvas canvas, float animationP
rogress) { |
| 842 if (!isNativeLibraryReady()) return; |
| 843 |
| 844 float floatAlpha = 1 - animationProgress; |
| 845 int rgbAlpha = (int) (255 * floatAlpha); |
| 846 canvas.save(); |
| 847 canvas.translate(0, -animationProgress * mBackgroundOverlayBounds.height
()); |
| 848 canvas.clipRect(mBackgroundOverlayBounds); |
| 849 |
| 850 // Draw the background of the view we are leaving. |
| 851 mTabSwitcherAnimationBgOverlay.setBounds( |
| 852 0, 0, getMeasuredWidth(), getMeasuredHeight()); |
| 853 if (isLocationBarShownInNTP()) { |
| 854 float ntpTransitionPercentage = mUrlExpansionPercent; |
| 855 boolean shouldDrawWhite = ntpTransitionPercentage != 1.0f; |
| 856 mTabSwitcherAnimationBgOverlay.setColor(shouldDrawWhite |
| 857 ? Color.WHITE : getToolbarColorForVisualState(VisualState.NO
RMAL)); |
| 858 } |
| 859 mTabSwitcherAnimationBgOverlay.draw(canvas); |
| 860 |
| 861 float previousAlpha = 0.f; |
| 862 if (mHomeButton.getVisibility() != View.GONE) { |
| 863 // Draw the New Tab button used in the URL view. |
| 864 previousAlpha = mHomeButton.getAlpha(); |
| 865 mHomeButton.setAlpha(previousAlpha * floatAlpha); |
| 866 drawChild(canvas, mHomeButton, SystemClock.uptimeMillis()); |
| 867 mHomeButton.setAlpha(previousAlpha); |
| 868 } |
| 869 |
| 870 // Draw the location/URL bar. |
| 871 previousAlpha = mPhoneLocationBar.getAlpha(); |
| 872 mPhoneLocationBar.setAlpha(previousAlpha * floatAlpha); |
| 873 // If the location bar is now fully transparent, do not bother drawing i
t. |
| 874 if (mPhoneLocationBar.getAlpha() != 0) { |
| 875 drawChild(canvas, mPhoneLocationBar, SystemClock.uptimeMillis()); |
| 876 } |
| 877 mPhoneLocationBar.setAlpha(previousAlpha); |
| 878 |
| 879 // Draw the tab stack button and associated text. |
| 880 translateCanvasToView(this, mToolbarButtonsContainer, canvas); |
| 881 |
| 882 if (mTabSwitcherAnimationTabStackDrawable != null |
| 883 && mToggleTabStackButton.getVisibility() != View.GONE) { |
| 884 // Draw the tab stack button image. |
| 885 canvas.save(); |
| 886 translateCanvasToView(mToolbarButtonsContainer, mToggleTabStackButto
n, canvas); |
| 887 |
| 888 int backgroundWidth = mToggleTabStackButton.getDrawable().getIntrins
icWidth(); |
| 889 int backgroundHeight = mToggleTabStackButton.getDrawable().getIntrin
sicHeight(); |
| 890 int backgroundLeft = (mToggleTabStackButton.getWidth() |
| 891 - mToggleTabStackButton.getPaddingLeft() |
| 892 - mToggleTabStackButton.getPaddingRight() - backgroundWidth)
/ 2; |
| 893 backgroundLeft += mToggleTabStackButton.getPaddingLeft(); |
| 894 int backgroundTop = (mToggleTabStackButton.getHeight() |
| 895 - mToggleTabStackButton.getPaddingTop() |
| 896 - mToggleTabStackButton.getPaddingBottom() - backgroundHeigh
t) / 2; |
| 897 backgroundTop += mToggleTabStackButton.getPaddingTop(); |
| 898 canvas.translate(backgroundLeft, backgroundTop); |
| 899 |
| 900 mTabSwitcherAnimationTabStackDrawable.setAlpha(rgbAlpha); |
| 901 mTabSwitcherAnimationTabStackDrawable.draw(canvas); |
| 902 canvas.restore(); |
| 903 } |
| 904 |
| 905 // Draw the menu button if necessary. |
| 906 if (mTabSwitcherAnimationMenuDrawable != null) { |
| 907 mTabSwitcherAnimationMenuDrawable.setBounds( |
| 908 mMenuButton.getPaddingLeft(), mMenuButton.getPaddingTop(), |
| 909 mMenuButton.getWidth() - mMenuButton.getPaddingRight(), |
| 910 mMenuButton.getHeight() - mMenuButton.getPaddingBottom()); |
| 911 translateCanvasToView(mToolbarButtonsContainer, mMenuButton, canvas)
; |
| 912 mTabSwitcherAnimationMenuDrawable.setAlpha(rgbAlpha); |
| 913 mTabSwitcherAnimationMenuDrawable.draw(canvas); |
| 914 } |
| 915 |
| 916 canvas.restore(); |
| 917 } |
| 918 |
| 919 @Override |
| 920 public void doInvalidate() { |
| 921 postInvalidateOnAnimation(); |
| 922 } |
| 923 |
| 924 /** |
| 925 * Translates the canvas to ensure the specified view's coordinates are at 0
, 0. |
| 926 * |
| 927 * @param from The view the canvas is currently translated to. |
| 928 * @param to The view to translate to. |
| 929 * @param canvas The canvas to be translated. |
| 930 * |
| 931 * @throws IllegalArgumentException if {@code from} is not an ancestor of {@
code to}. |
| 932 */ |
| 933 private static void translateCanvasToView(View from, View to, Canvas canvas) |
| 934 throws IllegalArgumentException { |
| 935 assert from != null; |
| 936 assert to != null; |
| 937 while (to != from) { |
| 938 canvas.translate(to.getLeft(), to.getTop()); |
| 939 if (!(to.getParent() instanceof View)) { |
| 940 throw new IllegalArgumentException("View 'to' was not a desenden
t of 'from'."); |
| 941 } |
| 942 to = (View) to.getParent(); |
| 943 } |
| 944 } |
| 945 |
| 946 @Override |
| 947 protected boolean drawChild(Canvas canvas, View child, long drawingTime) { |
| 948 if (child == mPhoneLocationBar) return drawLocationBar(canvas, drawingTi
me); |
| 949 boolean clipped = false; |
| 950 |
| 951 if (mLocationBarBackground != null |
| 952 && ((!mInTabSwitcherMode && !mTabSwitcherModeViews.contains(chil
d)) |
| 953 || (mInTabSwitcherMode && mBrowsingModeViews.contains(ch
ild)))) { |
| 954 canvas.save(); |
| 955 if (mUrlExpansionPercent != 0f && mUrlViewportBounds.top < child.get
Bottom()) { |
| 956 // For other child views, use the inverse clipping of the URL vi
ewport. |
| 957 // Only necessary during animations. |
| 958 // Hardware mode does not support unioned clip regions, so clip
using the |
| 959 // appropriate bounds based on whether the child is to the left
or right of the |
| 960 // location bar. |
| 961 boolean isLeft = (child == mNewTabButton || child == mHomeButton
) |
| 962 ^ LocalizationUtils.isLayoutRtl(); |
| 963 |
| 964 int clipTop = mUrlViewportBounds.top; |
| 965 int clipBottom = mUrlViewportBounds.bottom; |
| 966 boolean verticalClip = false; |
| 967 if (mPhoneLocationBar.getTranslationY() > 0f) { |
| 968 clipTop = child.getTop(); |
| 969 clipBottom = mUrlViewportBounds.top; |
| 970 verticalClip = true; |
| 971 } |
| 972 |
| 973 if (isLeft) { |
| 974 canvas.clipRect( |
| 975 0, clipTop, |
| 976 verticalClip ? child.getMeasuredWidth() : mUrlViewpo
rtBounds.left, |
| 977 clipBottom); |
| 978 } else { |
| 979 canvas.clipRect( |
| 980 verticalClip ? 0 : mUrlViewportBounds.right, |
| 981 clipTop, getMeasuredWidth(), clipBottom); |
| 982 } |
| 983 } |
| 984 clipped = true; |
| 985 } |
| 986 boolean retVal = super.drawChild(canvas, child, drawingTime); |
| 987 if (clipped) canvas.restore(); |
| 988 return retVal; |
| 989 } |
| 990 |
| 991 private boolean drawLocationBar(Canvas canvas, long drawingTime) { |
| 992 boolean clipped = false; |
| 993 float locationBarClipLeft = 0; |
| 994 float locationBarClipRight = 0; |
| 995 float locationBarClipTop = 0; |
| 996 float locationBarClipBottom = 0; |
| 997 |
| 998 if (mLocationBarBackground != null && (!mInTabSwitcherMode || mTextureCa
ptureMode)) { |
| 999 canvas.save(); |
| 1000 int backgroundAlpha = mUrlBackgroundAlpha; |
| 1001 if (mTabSwitcherModeAnimation != null) { |
| 1002 // Fade out/in the location bar towards the beginning of the ani
mations to avoid |
| 1003 // large jumps of stark white. |
| 1004 backgroundAlpha = |
| 1005 (int) (Math.pow(mPhoneLocationBar.getAlpha(), 3) * backg
roundAlpha); |
| 1006 } else if (getToolbarDataProvider().isUsingBrandColor() |
| 1007 && !mBrandColorTransitionActive) { |
| 1008 int unfocusedAlpha = mUnfocusedLocationBarUsesTransparentBg |
| 1009 ? LOCATION_BAR_TRANSPARENT_BACKGROUND_ALPHA : 255; |
| 1010 backgroundAlpha = |
| 1011 (int) (mUrlExpansionPercent * (255 - unfocusedAlpha) + u
nfocusedAlpha); |
| 1012 } |
| 1013 mLocationBarBackground.setAlpha(backgroundAlpha); |
| 1014 |
| 1015 if (mPhoneLocationBar.getAlpha() > 0 || mForceDrawLocationBarBackgro
und) { |
| 1016 mLocationBarBackground.setBounds( |
| 1017 mUrlViewportBounds.left + mLocationBarBackgroundOffset.l
eft, |
| 1018 mUrlViewportBounds.top + mLocationBarBackgroundOffset.to
p, |
| 1019 mUrlViewportBounds.right + mLocationBarBackgroundOffset.
right, |
| 1020 mUrlViewportBounds.bottom + mLocationBarBackgroundOffset
.bottom); |
| 1021 mLocationBarBackground.draw(canvas); |
| 1022 } |
| 1023 |
| 1024 locationBarClipLeft = mUrlViewportBounds.left + mUrlBackgroundPaddin
g.left |
| 1025 + mLocationBarBackgroundOffset.left; |
| 1026 locationBarClipRight = mUrlViewportBounds.right - mUrlBackgroundPadd
ing.right |
| 1027 + mLocationBarBackgroundOffset.right; |
| 1028 |
| 1029 // When unexpanded, the location bar's visible content boundaries ar
e inset from the |
| 1030 // viewport used to draw the background. During expansion transitio
ns, compensation |
| 1031 // is applied to increase the clip regions such that when the locati
on bar converts |
| 1032 // to the narrower collapsed layout that the visible content is the
same. |
| 1033 if (mUrlExpansionPercent != 1f) { |
| 1034 int leftDelta = mUnfocusedLocationBarLayoutLeft - getViewBoundsL
eftOfLocationBar(); |
| 1035 int rightDelta = getViewBoundsRightOfLocationBar() |
| 1036 - mUnfocusedLocationBarLayoutLeft |
| 1037 - mUnfocusedLocationBarLayoutWidth; |
| 1038 float inversePercent = 1f - mUrlExpansionPercent; |
| 1039 locationBarClipLeft += leftDelta * inversePercent; |
| 1040 locationBarClipRight -= rightDelta * inversePercent; |
| 1041 } |
| 1042 |
| 1043 locationBarClipTop = mUrlViewportBounds.top + mUrlBackgroundPadding.
top |
| 1044 + mLocationBarBackgroundOffset.top; |
| 1045 locationBarClipBottom = mUrlViewportBounds.bottom - mUrlBackgroundPa
dding.bottom |
| 1046 + mLocationBarBackgroundOffset.bottom; |
| 1047 // Clip the location bar child to the URL viewport calculated in onD
raw. |
| 1048 canvas.clipRect( |
| 1049 locationBarClipLeft, locationBarClipTop, |
| 1050 locationBarClipRight, locationBarClipBottom); |
| 1051 clipped = true; |
| 1052 } |
| 1053 |
| 1054 boolean retVal = super.drawChild(canvas, mPhoneLocationBar, drawingTime)
; |
| 1055 |
| 1056 if (clipped) canvas.restore(); |
| 1057 return retVal; |
| 1058 } |
| 1059 |
| 1060 @Override |
| 1061 protected void onSizeChanged(int w, int h, int oldw, int oldh) { |
| 1062 mBackgroundOverlayBounds.set(0, 0, w, mToolbarHeightWithoutShadow); |
| 1063 if (mTabSwitcherAnimationBgOverlay != null) { |
| 1064 mTabSwitcherAnimationBgOverlay.setBounds(0, 0, w, h); |
| 1065 } |
| 1066 super.onSizeChanged(w, h, oldw, oldh); |
| 1067 } |
| 1068 |
| 1069 @Override |
| 1070 protected void onAttachedToWindow() { |
| 1071 super.onAttachedToWindow(); |
| 1072 mToolbarShadow = (ImageView) getRootView().findViewById(R.id.toolbar_sha
dow); |
| 1073 } |
| 1074 |
| 1075 @Override |
| 1076 public void draw(Canvas canvas) { |
| 1077 // If capturing a texture of the toolbar, ensure the alpha is set prior
to draw(...) being |
| 1078 // called. The alpha is being used prior to getting to draw(...), so up
dating the value |
| 1079 // after this point was having no affect. |
| 1080 if (mTextureCaptureMode) assert getAlpha() == 1f; |
| 1081 if (!mTextureCaptureMode && mClipRect != null) { |
| 1082 canvas.save(); |
| 1083 canvas.clipRect(mClipRect); |
| 1084 } |
| 1085 super.draw(canvas); |
| 1086 if (!mTextureCaptureMode && mClipRect != null) canvas.restore(); |
| 1087 } |
| 1088 |
| 1089 @Override |
| 1090 public void onStateRestored() { |
| 1091 mToggleTabStackButton.setClickable(true); |
| 1092 } |
| 1093 |
| 1094 @Override |
| 1095 public boolean isReadyForTextureCapture() { |
| 1096 return !(mInTabSwitcherMode || mTabSwitcherModeAnimation != null |
| 1097 || urlHasFocus() || mUrlFocusChangeInProgress); |
| 1098 } |
| 1099 |
| 1100 @Override |
| 1101 protected void onNavigatedToDifferentPage() { |
| 1102 super.onNavigatedToDifferentPage(); |
| 1103 if (FeatureUtilities.isDocumentMode(getContext())) { |
| 1104 mUrlContainer.setTrailingTextVisible(true); |
| 1105 } |
| 1106 } |
| 1107 |
| 1108 @Override |
| 1109 public void setLoadProgress(int progress) { |
| 1110 super.setLoadProgress(progress); |
| 1111 if (FeatureUtilities.isDocumentMode(getContext()) && progress == 100) { |
| 1112 mUrlContainer.setTrailingTextVisible(false); |
| 1113 } |
| 1114 } |
| 1115 |
| 1116 @Override |
| 1117 public void finishAnimations() { |
| 1118 mClipRect = null; |
| 1119 if (mTabSwitcherModeAnimation != null) { |
| 1120 mTabSwitcherModeAnimation.end(); |
| 1121 mTabSwitcherModeAnimation = null; |
| 1122 } |
| 1123 if (mDelayedTabSwitcherModeAnimation != null) { |
| 1124 mDelayedTabSwitcherModeAnimation.end(); |
| 1125 mDelayedTabSwitcherModeAnimation = null; |
| 1126 } |
| 1127 } |
| 1128 |
| 1129 @Override |
| 1130 public void getLocationBarContentRect(Rect outRect) { |
| 1131 if (isLocationBarShownInNTP() && !isFocused()) { |
| 1132 outRect.setEmpty(); |
| 1133 return; |
| 1134 } |
| 1135 |
| 1136 super.getLocationBarContentRect(outRect); |
| 1137 } |
| 1138 |
| 1139 @Override |
| 1140 protected void onHomeButtonUpdate(boolean homeButtonEnabled) { |
| 1141 if (homeButtonEnabled) { |
| 1142 mHomeButton.setVisibility(urlHasFocus() || mInTabSwitcherMode ? INVI
SIBLE : VISIBLE); |
| 1143 if (!mBrowsingModeViews.contains(mHomeButton)) { |
| 1144 mBrowsingModeViews.add(mHomeButton); |
| 1145 } |
| 1146 } else { |
| 1147 mHomeButton.setVisibility(GONE); |
| 1148 mBrowsingModeViews.remove(mHomeButton); |
| 1149 } |
| 1150 } |
| 1151 |
| 1152 private ObjectAnimator createEnterTabSwitcherModeAnimation() { |
| 1153 ObjectAnimator enterAnimation = |
| 1154 ObjectAnimator.ofFloat(this, mTabSwitcherModePercentProperty, 1.
f); |
| 1155 enterAnimation.setDuration(TAB_SWITCHER_MODE_ENTER_ANIMATION_DURATION_MS
); |
| 1156 enterAnimation.setInterpolator(new LinearInterpolator()); |
| 1157 enterAnimation.addListener(new AnimatorListenerAdapter() { |
| 1158 @Override |
| 1159 public void onAnimationEnd(Animator animation) { |
| 1160 // This is to deal with the view going invisible when resuming t
he activity and |
| 1161 // running this animation. The view is still there and clickabl
e but does not |
| 1162 // render and only a layout triggers a refresh. See crbug.com/3
06890. |
| 1163 if (!mToggleTabStackButton.isEnabled()) requestLayout(); |
| 1164 } |
| 1165 }); |
| 1166 |
| 1167 return enterAnimation; |
| 1168 } |
| 1169 |
| 1170 private ObjectAnimator createExitTabSwitcherAnimation( |
| 1171 final boolean animateNormalToolbar) { |
| 1172 ObjectAnimator exitAnimation = |
| 1173 ObjectAnimator.ofFloat(this, mTabSwitcherModePercentProperty, 0.
f); |
| 1174 exitAnimation.setDuration(animateNormalToolbar |
| 1175 ? TAB_SWITCHER_MODE_EXIT_NORMAL_ANIMATION_DURATION_MS |
| 1176 : TAB_SWITCHER_MODE_EXIT_FADE_ANIMATION_DURATION_MS); |
| 1177 exitAnimation.setInterpolator(new LinearInterpolator()); |
| 1178 exitAnimation.addListener(new AnimatorListenerAdapter() { |
| 1179 @Override |
| 1180 public void onAnimationEnd(Animator animation) { |
| 1181 updateViewsForTabSwitcherMode(mInTabSwitcherMode); |
| 1182 } |
| 1183 }); |
| 1184 |
| 1185 return exitAnimation; |
| 1186 } |
| 1187 |
| 1188 private ObjectAnimator createPostExitTabSwitcherAnimation() { |
| 1189 ObjectAnimator exitAnimation = ObjectAnimator.ofFloat( |
| 1190 this, View.TRANSLATION_Y, -getHeight(), 0.f); |
| 1191 exitAnimation.setDuration(TAB_SWITCHER_MODE_POST_EXIT_ANIMATION_DURATION
_MS); |
| 1192 exitAnimation.setInterpolator(BakedBezierInterpolator.TRANSFORM_CURVE); |
| 1193 exitAnimation.addListener(new AnimatorListenerAdapter() { |
| 1194 @Override |
| 1195 public void onAnimationStart(Animator animation) { |
| 1196 updateViewsForTabSwitcherMode(mInTabSwitcherMode); |
| 1197 // On older builds, force an update to ensure the new visuals ar
e used |
| 1198 // when bringing in the toolbar. crbug.com/404571 |
| 1199 if (Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN) { |
| 1200 requestLayout(); |
| 1201 } |
| 1202 } |
| 1203 |
| 1204 @Override |
| 1205 public void onAnimationEnd(Animator animation) { |
| 1206 mDelayedTabSwitcherModeAnimation = null; |
| 1207 updateShadowVisibility(mInTabSwitcherMode); |
| 1208 updateViewsForTabSwitcherMode(mInTabSwitcherMode); |
| 1209 } |
| 1210 }); |
| 1211 |
| 1212 return exitAnimation; |
| 1213 } |
| 1214 |
| 1215 @Override |
| 1216 public void setTextureCaptureMode(boolean textureMode) { |
| 1217 assert mTextureCaptureMode != textureMode; |
| 1218 mTextureCaptureMode = textureMode; |
| 1219 if (mTextureCaptureMode) { |
| 1220 mPreTextureCaptureAlpha = getAlpha(); |
| 1221 setAlpha(1); |
| 1222 } else { |
| 1223 setAlpha(mPreTextureCaptureAlpha); |
| 1224 mPreTextureCaptureAlpha = 1f; |
| 1225 } |
| 1226 } |
| 1227 |
| 1228 private boolean isTabSwitcherAnimationRunning() { |
| 1229 return mUIAnimatingTabSwitcherTransition |
| 1230 || (mTabSwitcherModeAnimation != null && mTabSwitcherModeAnimati
on.isRunning()) |
| 1231 || (mDelayedTabSwitcherModeAnimation != null |
| 1232 && mDelayedTabSwitcherModeAnimation.isRunning())
; |
| 1233 } |
| 1234 |
| 1235 private void updateViewsForTabSwitcherMode(boolean isInTabSwitcherMode) { |
| 1236 int tabSwitcherViewsVisibility = isInTabSwitcherMode ? VISIBLE : INVISIB
LE; |
| 1237 int browsingViewsVisibility = isInTabSwitcherMode ? INVISIBLE : VISIBLE; |
| 1238 |
| 1239 for (View view : mTabSwitcherModeViews) { |
| 1240 view.setVisibility(tabSwitcherViewsVisibility); |
| 1241 } |
| 1242 for (View view : mBrowsingModeViews) { |
| 1243 view.setVisibility(browsingViewsVisibility); |
| 1244 } |
| 1245 getProgressBar().setVisibility( |
| 1246 isInTabSwitcherMode || isTabSwitcherAnimationRunning() ? INVISIB
LE : VISIBLE); |
| 1247 updateVisualsForToolbarState(isInTabSwitcherMode); |
| 1248 |
| 1249 } |
| 1250 |
| 1251 @Override |
| 1252 protected void setContentAttached(boolean attached) { |
| 1253 updateVisualsForToolbarState(mInTabSwitcherMode); |
| 1254 } |
| 1255 |
| 1256 @Override |
| 1257 protected void setTabSwitcherMode( |
| 1258 boolean inTabSwitcherMode, boolean showToolbar, boolean delayAnimati
on) { |
| 1259 if (mInTabSwitcherMode == inTabSwitcherMode) return; |
| 1260 |
| 1261 finishAnimations(); |
| 1262 |
| 1263 mDelayingTabSwitcherAnimation = delayAnimation; |
| 1264 |
| 1265 if (inTabSwitcherMode) { |
| 1266 if (mUrlFocusLayoutAnimator != null && mUrlFocusLayoutAnimator.isRun
ning()) { |
| 1267 mUrlFocusLayoutAnimator.end(); |
| 1268 mUrlFocusLayoutAnimator = null; |
| 1269 } |
| 1270 mNewTabButton.setEnabled(true); |
| 1271 updateViewsForTabSwitcherMode(true); |
| 1272 mTabSwitcherModeAnimation = createEnterTabSwitcherModeAnimation(); |
| 1273 } else { |
| 1274 if (!mDelayingTabSwitcherAnimation) { |
| 1275 mTabSwitcherModeAnimation = createExitTabSwitcherAnimation(showT
oolbar); |
| 1276 } |
| 1277 mUIAnimatingTabSwitcherTransition = true; |
| 1278 } |
| 1279 |
| 1280 mAnimateNormalToolbar = showToolbar; |
| 1281 mInTabSwitcherMode = inTabSwitcherMode; |
| 1282 if (mTabSwitcherModeAnimation != null) mTabSwitcherModeAnimation.start()
; |
| 1283 |
| 1284 if (SysUtils.isLowEndDevice()) finishAnimations(); |
| 1285 |
| 1286 postInvalidateOnAnimation(); |
| 1287 } |
| 1288 |
| 1289 @Override |
| 1290 protected void onTabSwitcherTransitionFinished() { |
| 1291 setAlpha(1.f); |
| 1292 mClipRect = null; |
| 1293 mUIAnimatingTabSwitcherTransition = false; |
| 1294 if (!mAnimateNormalToolbar) { |
| 1295 finishAnimations(); |
| 1296 updateVisualsForToolbarState(mInTabSwitcherMode); |
| 1297 } |
| 1298 |
| 1299 if (mDelayingTabSwitcherAnimation) { |
| 1300 mDelayingTabSwitcherAnimation = false; |
| 1301 mDelayedTabSwitcherModeAnimation = createPostExitTabSwitcherAnimatio
n(); |
| 1302 mDelayedTabSwitcherModeAnimation.start(); |
| 1303 } else { |
| 1304 updateViewsForTabSwitcherMode(mInTabSwitcherMode); |
| 1305 } |
| 1306 } |
| 1307 |
| 1308 private void updateOverlayDrawables() { |
| 1309 if (!isNativeLibraryReady()) return; |
| 1310 |
| 1311 VisualState overlayState = computeVisualState(false); |
| 1312 boolean visualStateChanged = mOverlayDrawablesVisualState != overlayStat
e; |
| 1313 |
| 1314 if (!visualStateChanged && mVisualState == VisualState.BRAND_COLOR |
| 1315 && getToolbarDataProvider().getPrimaryColor() |
| 1316 != mTabSwitcherAnimationBgOverlay.getColor()) { |
| 1317 visualStateChanged = true; |
| 1318 } |
| 1319 if (!visualStateChanged) return; |
| 1320 |
| 1321 mOverlayDrawablesVisualState = overlayState; |
| 1322 mTabSwitcherAnimationBgOverlay.setColor(getToolbarColorForVisualState( |
| 1323 mOverlayDrawablesVisualState)); |
| 1324 |
| 1325 if (shouldShowMenuButton()) { |
| 1326 Resources res = getResources(); |
| 1327 mTabSwitcherAnimationMenuDrawable = ApiCompatibilityUtils.getDrawabl
e( |
| 1328 res, R.drawable.btn_menu).mutate(); |
| 1329 mTabSwitcherAnimationMenuDrawable.setColorFilter(isIncognito() ? Col
or.WHITE |
| 1330 : getResources().getColor(R.color.light_normal_color), |
| 1331 PorterDuff.Mode.SRC_IN); |
| 1332 ((BitmapDrawable) mTabSwitcherAnimationMenuDrawable).setGravity(Grav
ity.CENTER); |
| 1333 } |
| 1334 } |
| 1335 |
| 1336 @Override |
| 1337 public void setOnTabSwitcherClickHandler(OnClickListener listener) { |
| 1338 mTabSwitcherListener = listener; |
| 1339 } |
| 1340 |
| 1341 @Override |
| 1342 public void setOnNewTabClickHandler(OnClickListener listener) { |
| 1343 mNewTabListener = listener; |
| 1344 } |
| 1345 |
| 1346 @Override |
| 1347 public boolean shouldIgnoreSwipeGesture() { |
| 1348 return super.shouldIgnoreSwipeGesture() || mUrlExpansionPercent > 0f; |
| 1349 } |
| 1350 |
| 1351 private Property<TextView, Integer> buildUrlScrollProperty( |
| 1352 final View containerView, final boolean isContainerRtl) { |
| 1353 // If the RTL-ness of the container view changes during an animation, th
e scroll values |
| 1354 // become invalid. If that happens, snap to the ending position and no
longer update. |
| 1355 return new Property<TextView, Integer>(Integer.class, "scrollX") { |
| 1356 private boolean mRtlStateInvalid; |
| 1357 |
| 1358 @Override |
| 1359 public Integer get(TextView view) { |
| 1360 return view.getScrollX(); |
| 1361 } |
| 1362 |
| 1363 @Override |
| 1364 public void set(TextView view, Integer scrollX) { |
| 1365 if (mRtlStateInvalid) return; |
| 1366 boolean rtl = ApiCompatibilityUtils.isLayoutRtl(containerView); |
| 1367 if (rtl != isContainerRtl) { |
| 1368 mRtlStateInvalid = true; |
| 1369 if (!rtl || mUrlBar.getLayout() != null) { |
| 1370 scrollX = 0; |
| 1371 if (rtl) { |
| 1372 scrollX = (int) view.getLayout().getPrimaryHorizonta
l(0); |
| 1373 scrollX -= view.getWidth(); |
| 1374 } |
| 1375 } |
| 1376 } |
| 1377 view.setScrollX(scrollX); |
| 1378 } |
| 1379 }; |
| 1380 } |
| 1381 |
| 1382 private void populateUrlFocusingAnimatorSet(List<Animator> animators) { |
| 1383 Animator animator = ObjectAnimator.ofFloat(this, mUrlFocusChangePercentP
roperty, 1f); |
| 1384 animator.setDuration(URL_FOCUS_CHANGE_ANIMATION_DURATION_MS); |
| 1385 animator.setInterpolator(BakedBezierInterpolator.TRANSFORM_CURVE); |
| 1386 animators.add(animator); |
| 1387 |
| 1388 for (int i = 0; i < mPhoneLocationBar.getChildCount(); i++) { |
| 1389 View childView = mPhoneLocationBar.getChildAt(i); |
| 1390 if (childView == mPhoneLocationBar.getFirstViewVisibleWhenFocused())
break; |
| 1391 animator = ObjectAnimator.ofFloat(childView, ALPHA, 0); |
| 1392 animator.setDuration(URL_FOCUS_CHANGE_ANIMATION_DURATION_MS); |
| 1393 animator.setInterpolator(BakedBezierInterpolator.TRANSFORM_CURVE); |
| 1394 animators.add(animator); |
| 1395 } |
| 1396 |
| 1397 float density = getContext().getResources().getDisplayMetrics().density; |
| 1398 boolean isRtl = ApiCompatibilityUtils.isLayoutRtl(this); |
| 1399 float toolbarButtonTranslationX = MathUtils.flipSignIf( |
| 1400 URL_FOCUS_TOOLBAR_BUTTONS_TRANSLATION_X_DP, isRtl) * density; |
| 1401 |
| 1402 animator = ObjectAnimator.ofFloat( |
| 1403 mMenuButton, TRANSLATION_X, toolbarButtonTranslationX); |
| 1404 animator.setDuration(URL_FOCUS_TOOLBAR_BUTTONS_DURATION_MS); |
| 1405 animator.setInterpolator(BakedBezierInterpolator.FADE_OUT_CURVE); |
| 1406 animators.add(animator); |
| 1407 |
| 1408 animator = ObjectAnimator.ofFloat(mMenuButton, ALPHA, 0); |
| 1409 animator.setDuration(URL_FOCUS_TOOLBAR_BUTTONS_DURATION_MS); |
| 1410 animator.setInterpolator(BakedBezierInterpolator.FADE_OUT_CURVE); |
| 1411 animators.add(animator); |
| 1412 |
| 1413 if (mToggleTabStackButton.getVisibility() != GONE) { |
| 1414 animator = ObjectAnimator.ofFloat( |
| 1415 mToggleTabStackButton, TRANSLATION_X, toolbarButtonTranslati
onX); |
| 1416 animator.setDuration(URL_FOCUS_TOOLBAR_BUTTONS_DURATION_MS); |
| 1417 animator.setInterpolator(BakedBezierInterpolator.FADE_OUT_CURVE); |
| 1418 animators.add(animator); |
| 1419 |
| 1420 animator = ObjectAnimator.ofFloat(mToggleTabStackButton, ALPHA, 0); |
| 1421 animator.setDuration(URL_FOCUS_TOOLBAR_BUTTONS_DURATION_MS); |
| 1422 animator.setInterpolator(BakedBezierInterpolator.FADE_OUT_CURVE); |
| 1423 animators.add(animator); |
| 1424 } |
| 1425 } |
| 1426 |
| 1427 private void populateUrlClearFocusingAnimatorSet(List<Animator> animators) { |
| 1428 Animator animator = ObjectAnimator.ofFloat(this, mUrlFocusChangePercentP
roperty, 0f); |
| 1429 animator.setDuration(URL_FOCUS_CHANGE_ANIMATION_DURATION_MS); |
| 1430 animator.setInterpolator(BakedBezierInterpolator.TRANSFORM_CURVE); |
| 1431 animators.add(animator); |
| 1432 |
| 1433 animator = ObjectAnimator.ofFloat(mMenuButton, TRANSLATION_X, 0); |
| 1434 animator.setDuration(URL_FOCUS_TOOLBAR_BUTTONS_DURATION_MS); |
| 1435 animator.setStartDelay(URL_CLEAR_FOCUS_MENU_DELAY_MS); |
| 1436 animator.setInterpolator(BakedBezierInterpolator.TRANSFORM_CURVE); |
| 1437 animators.add(animator); |
| 1438 |
| 1439 animator = ObjectAnimator.ofFloat(mMenuButton, ALPHA, 1); |
| 1440 animator.setDuration(URL_FOCUS_TOOLBAR_BUTTONS_DURATION_MS); |
| 1441 animator.setStartDelay(URL_CLEAR_FOCUS_MENU_DELAY_MS); |
| 1442 animator.setInterpolator(BakedBezierInterpolator.TRANSFORM_CURVE); |
| 1443 animators.add(animator); |
| 1444 |
| 1445 if (mToggleTabStackButton.getVisibility() != GONE) { |
| 1446 animator = ObjectAnimator.ofFloat(mToggleTabStackButton, TRANSLATION
_X, 0); |
| 1447 animator.setDuration(URL_FOCUS_TOOLBAR_BUTTONS_DURATION_MS); |
| 1448 animator.setStartDelay(URL_CLEAR_FOCUS_TABSTACK_DELAY_MS); |
| 1449 animator.setInterpolator(BakedBezierInterpolator.TRANSFORM_CURVE); |
| 1450 animators.add(animator); |
| 1451 |
| 1452 animator = ObjectAnimator.ofFloat(mToggleTabStackButton, ALPHA, 1); |
| 1453 animator.setDuration(URL_FOCUS_TOOLBAR_BUTTONS_DURATION_MS); |
| 1454 animator.setStartDelay(URL_CLEAR_FOCUS_TABSTACK_DELAY_MS); |
| 1455 animator.setInterpolator(BakedBezierInterpolator.TRANSFORM_CURVE); |
| 1456 animators.add(animator); |
| 1457 } |
| 1458 |
| 1459 for (int i = 0; i < mPhoneLocationBar.getChildCount(); i++) { |
| 1460 View childView = mPhoneLocationBar.getChildAt(i); |
| 1461 if (childView == mPhoneLocationBar.getFirstViewVisibleWhenFocused())
break; |
| 1462 animator = ObjectAnimator.ofFloat(childView, ALPHA, 1); |
| 1463 animator.setStartDelay(URL_FOCUS_TOOLBAR_BUTTONS_DURATION_MS); |
| 1464 animator.setDuration(URL_CLEAR_FOCUS_MENU_DELAY_MS); |
| 1465 animator.setInterpolator(BakedBezierInterpolator.TRANSFORM_CURVE); |
| 1466 animators.add(animator); |
| 1467 } |
| 1468 |
| 1469 if (isLocationBarShownInNTP() && mNtpSearchBoxScrollPercent == 0f) retur
n; |
| 1470 |
| 1471 if (!FeatureUtilities.isDocumentMode(getContext()) |
| 1472 || mPhoneLocationBar.showingQueryInTheOmnibox()) { |
| 1473 // The call to getLayout() can return null briefly during text chang
es, but as it |
| 1474 // is only needed for RTL calculations, we proceed if the location b
ar is showing |
| 1475 // LTR content. |
| 1476 boolean isLocationBarRtl = ApiCompatibilityUtils.isLayoutRtl(mPhoneL
ocationBar); |
| 1477 if (!isLocationBarRtl || mUrlBar.getLayout() != null) { |
| 1478 int urlBarStartScrollX = 0; |
| 1479 if (isLocationBarRtl) { |
| 1480 urlBarStartScrollX = (int) mUrlBar.getLayout().getPrimaryHor
izontal(0); |
| 1481 urlBarStartScrollX -= mUrlBar.getWidth(); |
| 1482 } |
| 1483 |
| 1484 // If the scroll position matches the current scroll position, d
o not trigger |
| 1485 // this animation as it will cause visible jumps when going from
cleared text |
| 1486 // back to page URLs (despite it continually calling setScrollX
with the same |
| 1487 // number). |
| 1488 if (mUrlBar.getScrollX() != urlBarStartScrollX) { |
| 1489 animator = ObjectAnimator.ofInt( |
| 1490 mUrlBar, |
| 1491 buildUrlScrollProperty(mPhoneLocationBar, isLocation
BarRtl), |
| 1492 urlBarStartScrollX); |
| 1493 animator.setDuration(URL_FOCUS_CHANGE_ANIMATION_DURATION_MS)
; |
| 1494 animator.setInterpolator(BakedBezierInterpolator.TRANSFORM_C
URVE); |
| 1495 animators.add(animator); |
| 1496 } |
| 1497 } |
| 1498 } |
| 1499 } |
| 1500 |
| 1501 @Override |
| 1502 public void onUrlFocusChange(final boolean hasFocus) { |
| 1503 super.onUrlFocusChange(hasFocus); |
| 1504 |
| 1505 triggerUrlFocusAnimation(hasFocus); |
| 1506 |
| 1507 TransitionDrawable shadowDrawable = (TransitionDrawable) mToolbarShadow.
getDrawable(); |
| 1508 if (hasFocus) { |
| 1509 shadowDrawable.startTransition(URL_FOCUS_CHANGE_ANIMATION_DURATION_M
S); |
| 1510 } else { |
| 1511 shadowDrawable.reverseTransition(URL_FOCUS_CHANGE_ANIMATION_DURATION
_MS); |
| 1512 } |
| 1513 } |
| 1514 |
| 1515 private void triggerUrlFocusAnimation(final boolean hasFocus) { |
| 1516 if (mUrlFocusLayoutAnimator != null && mUrlFocusLayoutAnimator.isRunning
()) { |
| 1517 mUrlFocusLayoutAnimator.cancel(); |
| 1518 mUrlFocusLayoutAnimator = null; |
| 1519 } |
| 1520 |
| 1521 List<Animator> animators = new ArrayList<Animator>(); |
| 1522 if (hasFocus) { |
| 1523 populateUrlFocusingAnimatorSet(animators); |
| 1524 } else { |
| 1525 populateUrlClearFocusingAnimatorSet(animators); |
| 1526 } |
| 1527 mUrlFocusLayoutAnimator = new AnimatorSet(); |
| 1528 mUrlFocusLayoutAnimator.playTogether(animators); |
| 1529 |
| 1530 mUrlFocusChangeInProgress = true; |
| 1531 mUrlFocusLayoutAnimator.addListener(new AnimatorListenerAdapter() { |
| 1532 private boolean mCanceled; |
| 1533 |
| 1534 @Override |
| 1535 public void onAnimationStart(Animator animation) { |
| 1536 if (!hasFocus) { |
| 1537 mDisableLocationBarRelayout = true; |
| 1538 } else { |
| 1539 mLayoutLocationBarInFocusedMode = true; |
| 1540 requestLayout(); |
| 1541 } |
| 1542 } |
| 1543 |
| 1544 @Override |
| 1545 public void onAnimationCancel(Animator animation) { |
| 1546 mCanceled = true; |
| 1547 } |
| 1548 |
| 1549 @Override |
| 1550 public void onAnimationEnd(Animator animation) { |
| 1551 if (mCanceled) return; |
| 1552 |
| 1553 if (!hasFocus) { |
| 1554 mDisableLocationBarRelayout = false; |
| 1555 mLayoutLocationBarInFocusedMode = false; |
| 1556 requestLayout(); |
| 1557 } |
| 1558 mPhoneLocationBar.finishUrlFocusChange(hasFocus); |
| 1559 mUrlFocusChangeInProgress = false; |
| 1560 } |
| 1561 }); |
| 1562 mUrlFocusLayoutAnimator.start(); |
| 1563 } |
| 1564 |
| 1565 @Override |
| 1566 protected boolean shouldShowMenuButton() { |
| 1567 return !mPhoneLocationBar.showMenuButtonInOmnibox() && super.shouldShowM
enuButton(); |
| 1568 } |
| 1569 |
| 1570 @Override |
| 1571 protected void updateTabCountVisuals(int numberOfTabs) { |
| 1572 if (mToggleTabStackButton == null) return; |
| 1573 mHomeButton.setEnabled(true); |
| 1574 |
| 1575 mToggleTabStackButton.setEnabled(numberOfTabs >= 1); |
| 1576 mToggleTabStackButton.setContentDescription( |
| 1577 getResources().getString(R.string.accessibility_toolbar_btn_tabs
witcher_toggle, |
| 1578 numberOfTabs)); |
| 1579 mTabSwitcherButtonDrawableLight.updateForTabCount(numberOfTabs, isIncogn
ito()); |
| 1580 mTabSwitcherButtonDrawable.updateForTabCount(numberOfTabs, isIncognito()
); |
| 1581 |
| 1582 boolean useTabStackDrawableLight = isIncognito(); |
| 1583 if (mTabSwitcherAnimationTabStackDrawable == null |
| 1584 || mIsOverlayTabStackDrawableLight != useTabStackDrawableLight)
{ |
| 1585 mTabSwitcherAnimationTabStackDrawable = |
| 1586 TabSwitcherDrawable.createTabSwitcherDrawable( |
| 1587 getResources(), useTabStackDrawableLight); |
| 1588 int[] stateSet = {android.R.attr.state_enabled}; |
| 1589 mTabSwitcherAnimationTabStackDrawable.setState(stateSet); |
| 1590 mTabSwitcherAnimationTabStackDrawable.setBounds( |
| 1591 mToggleTabStackButton.getDrawable().getBounds()); |
| 1592 mIsOverlayTabStackDrawableLight = useTabStackDrawableLight; |
| 1593 } |
| 1594 |
| 1595 if (mTabSwitcherAnimationTabStackDrawable != null) { |
| 1596 mTabSwitcherAnimationTabStackDrawable.updateForTabCount( |
| 1597 numberOfTabs, isIncognito()); |
| 1598 } |
| 1599 } |
| 1600 |
| 1601 @Override |
| 1602 protected void onTabContentViewChanged() { |
| 1603 super.onTabContentViewChanged(); |
| 1604 updateNtpAnimationState(); |
| 1605 updateVisualsForToolbarState(mInTabSwitcherMode); |
| 1606 } |
| 1607 |
| 1608 @Override |
| 1609 protected void onTabOrModelChanged() { |
| 1610 super.onTabOrModelChanged(); |
| 1611 updateNtpAnimationState(); |
| 1612 updateVisualsForToolbarState(mInTabSwitcherMode); |
| 1613 } |
| 1614 |
| 1615 @Override |
| 1616 protected void onPrimaryColorChanged() { |
| 1617 super.onPrimaryColorChanged(); |
| 1618 if (mBrandColorTransitionActive) mBrandColorTransitionAnimation.cancel()
; |
| 1619 final int initialColor = mToolbarBackground.getColor(); |
| 1620 final int finalColor = getToolbarDataProvider().getPrimaryColor(); |
| 1621 if (initialColor == finalColor) return; |
| 1622 boolean shouldUseOpaque = BrandColorUtils.shouldUseOpaqueTextboxBackgrou
nd(finalColor); |
| 1623 final int initialAlpha = mUrlBackgroundAlpha; |
| 1624 final int finalAlpha = |
| 1625 shouldUseOpaque ? 255 : LOCATION_BAR_TRANSPARENT_BACKGROUND_ALPH
A; |
| 1626 final boolean shouldAnimateAlpha = initialAlpha != finalAlpha; |
| 1627 mBrandColorTransitionAnimation = ValueAnimator.ofFloat(0, 1) |
| 1628 .setDuration(BRAND_COLOR_TRANSITION_DURATION_MS); |
| 1629 mBrandColorTransitionAnimation.setInterpolator(BakedBezierInterpolator.T
RANSFORM_CURVE); |
| 1630 mBrandColorTransitionAnimation.addUpdateListener(new AnimatorUpdateListe
ner() { |
| 1631 @Override |
| 1632 public void onAnimationUpdate(ValueAnimator animation) { |
| 1633 float fraction = animation.getAnimatedFraction(); |
| 1634 int red = (int) (Color.red(initialColor) |
| 1635 + fraction * (Color.red(finalColor) - Color.red(initialC
olor))); |
| 1636 int green = (int) (Color.green(initialColor) |
| 1637 + fraction * (Color.green(finalColor) - Color.green(init
ialColor))); |
| 1638 int blue = (int) (Color.blue(initialColor) |
| 1639 + fraction * (Color.blue(finalColor) - Color.blue(initia
lColor))); |
| 1640 if (shouldAnimateAlpha) { |
| 1641 mUrlBackgroundAlpha = |
| 1642 (int) (initialAlpha + fraction * (finalAlpha - initi
alAlpha)); |
| 1643 } |
| 1644 updateToolbarBackground(Color.rgb(red, green, blue)); |
| 1645 } |
| 1646 }); |
| 1647 mBrandColorTransitionAnimation.addListener(new AnimatorListenerAdapter()
{ |
| 1648 @Override |
| 1649 public void onAnimationEnd(Animator animation) { |
| 1650 mBrandColorTransitionActive = false; |
| 1651 updateVisualsForToolbarState(mInTabSwitcherMode); |
| 1652 } |
| 1653 }); |
| 1654 mBrandColorTransitionAnimation.start(); |
| 1655 mBrandColorTransitionActive = true; |
| 1656 } |
| 1657 |
| 1658 private void updateNtpAnimationState() { |
| 1659 // Store previous NTP scroll before calling reset as that clears this va
lue. |
| 1660 boolean wasShowingNtp = mVisibleNewTabPage != null; |
| 1661 float previousNtpScrollPercent = mNtpSearchBoxScrollPercent; |
| 1662 |
| 1663 resetNtpAnimationValues(); |
| 1664 if (mVisibleNewTabPage != null) { |
| 1665 mVisibleNewTabPage.setSearchBoxScrollListener(null); |
| 1666 mVisibleNewTabPage = null; |
| 1667 } |
| 1668 mVisibleNewTabPage = getToolbarDataProvider().getNewTabPageForCurrentTab
(); |
| 1669 if (mVisibleNewTabPage != null && mVisibleNewTabPage.isLocationBarShownI
nNTP()) { |
| 1670 mVisibleNewTabPage.setSearchBoxScrollListener(this); |
| 1671 requestLayout(); |
| 1672 } else if (wasShowingNtp) { |
| 1673 // Convert the previous NTP scroll percentage to URL focus percentag
e because that |
| 1674 // will give a nicer transition animation from the expanded NTP omni
box to the |
| 1675 // collapsed normal omnibox on other non-NTP pages. |
| 1676 if (previousNtpScrollPercent > 0f) { |
| 1677 mUrlFocusChangePercent = |
| 1678 Math.max(previousNtpScrollPercent, mUrlFocusChangePercen
t); |
| 1679 triggerUrlFocusAnimation(false); |
| 1680 } |
| 1681 requestLayout(); |
| 1682 } |
| 1683 } |
| 1684 |
| 1685 @Override |
| 1686 protected void onDefaultSearchEngineChanged() { |
| 1687 super.onDefaultSearchEngineChanged(); |
| 1688 // Post an update for the toolbar state, which will allow all other list
eners |
| 1689 // for the search engine change to update before we check on the state o
f the |
| 1690 // world for a UI update. |
| 1691 // TODO(tedchoc): Move away from updating based on the search engine cha
nge and instead |
| 1692 // add the toolbar as a listener to the NewTabPage and ud
pate only when |
| 1693 // it notifies the listeners that it has changed it's sta
te. |
| 1694 post(new Runnable() { |
| 1695 @Override |
| 1696 public void run() { |
| 1697 updateVisualsForToolbarState(mInTabSwitcherMode); |
| 1698 updateNtpAnimationState(); |
| 1699 } |
| 1700 }); |
| 1701 } |
| 1702 |
| 1703 @Override |
| 1704 protected void handleFindToolbarStateChange(boolean showing) { |
| 1705 setVisibility(showing ? View.GONE : View.VISIBLE); |
| 1706 TransitionDrawable shadowDrawable = (TransitionDrawable) mToolbarShadow.
getDrawable(); |
| 1707 if (showing) { |
| 1708 shadowDrawable.startTransition(URL_FOCUS_CHANGE_ANIMATION_DURATION_M
S); |
| 1709 } else { |
| 1710 shadowDrawable.reverseTransition(URL_FOCUS_CHANGE_ANIMATION_DURATION
_MS); |
| 1711 } |
| 1712 } |
| 1713 |
| 1714 private boolean isLocationBarShownInNTP() { |
| 1715 NewTabPage ntp = getToolbarDataProvider().getNewTabPageForCurrentTab(); |
| 1716 return ntp != null && ntp.isLocationBarShownInNTP(); |
| 1717 } |
| 1718 |
| 1719 private void updateShadowVisibility(boolean isInTabSwitcherMode) { |
| 1720 boolean shouldDrawShadow = !isInTabSwitcherMode && !isTabSwitcherAnimati
onRunning(); |
| 1721 int shadowVisibility = shouldDrawShadow ? View.VISIBLE : View.INVISIBLE; |
| 1722 |
| 1723 if (mToolbarShadow.getVisibility() != shadowVisibility) { |
| 1724 mToolbarShadow.setVisibility(shadowVisibility); |
| 1725 } |
| 1726 } |
| 1727 |
| 1728 private VisualState computeVisualState(boolean isInTabSwitcherMode) { |
| 1729 if (isInTabSwitcherMode && isIncognito()) return VisualState.TAB_SWITCHE
R_INCOGNITO; |
| 1730 if (isInTabSwitcherMode && !isIncognito()) return VisualState.TAB_SWITCH
ER_NORMAL; |
| 1731 if (isLocationBarShownInNTP()) return VisualState.NEW_TAB_NORMAL; |
| 1732 if (isIncognito()) return VisualState.INCOGNITO; |
| 1733 if (getToolbarDataProvider().isUsingBrandColor()) return VisualState.BRA
ND_COLOR; |
| 1734 return VisualState.NORMAL; |
| 1735 } |
| 1736 |
| 1737 private void updateVisualsForToolbarState(boolean isInTabSwitcherMode) { |
| 1738 if (mBrandColorTransitionActive) return; |
| 1739 final boolean isIncognito = isIncognito(); |
| 1740 |
| 1741 VisualState visualState = computeVisualState(isInTabSwitcherMode); |
| 1742 boolean visualStateChanged = mVisualState != visualState; |
| 1743 |
| 1744 int currentPrimaryColor = getToolbarDataProvider().getPrimaryColor(); |
| 1745 if (mVisualState == VisualState.BRAND_COLOR && !visualStateChanged) { |
| 1746 boolean useLightToolbarDrawables = |
| 1747 BrandColorUtils.shouldUseLightDrawablesForToolbar(currentPri
maryColor); |
| 1748 boolean unfocusedLocationBarUsesTransparentBg = |
| 1749 !BrandColorUtils.shouldUseOpaqueTextboxBackground(currentPri
maryColor); |
| 1750 if (useLightToolbarDrawables != mUseLightToolbarDrawables |
| 1751 || unfocusedLocationBarUsesTransparentBg |
| 1752 != mUnfocusedLocationBarUsesTransparentBg) { |
| 1753 visualStateChanged = true; |
| 1754 } else { |
| 1755 updateToolbarBackground(VisualState.BRAND_COLOR); |
| 1756 } |
| 1757 } |
| 1758 |
| 1759 mVisualState = visualState; |
| 1760 |
| 1761 updateOverlayDrawables(); |
| 1762 updateShadowVisibility(isInTabSwitcherMode); |
| 1763 if (!visualStateChanged) { |
| 1764 if (mVisualState == VisualState.NEW_TAB_NORMAL) { |
| 1765 updateNtpTransitionAnimation( |
| 1766 getToolbarDataProvider().getNewTabPageForCurrentTab()); |
| 1767 } |
| 1768 return; |
| 1769 } |
| 1770 |
| 1771 mUseLightToolbarDrawables = false; |
| 1772 mUnfocusedLocationBarUsesTransparentBg = false; |
| 1773 mUrlBackgroundAlpha = 255; |
| 1774 int progressBarResource = R.drawable.progress_bar; |
| 1775 updateToolbarBackground(mVisualState); |
| 1776 if (isInTabSwitcherMode) { |
| 1777 mUseLightToolbarDrawables = true; |
| 1778 mUrlBackgroundAlpha = LOCATION_BAR_TRANSPARENT_BACKGROUND_ALPHA; |
| 1779 progressBarResource = R.drawable.progress_bar_white; |
| 1780 } else if (isIncognito()) { |
| 1781 mUseLightToolbarDrawables = true; |
| 1782 mUrlBackgroundAlpha = LOCATION_BAR_TRANSPARENT_BACKGROUND_ALPHA; |
| 1783 progressBarResource = R.drawable.progress_bar_white; |
| 1784 } else if (mVisualState == VisualState.BRAND_COLOR) { |
| 1785 mUseLightToolbarDrawables = |
| 1786 BrandColorUtils.shouldUseLightDrawablesForToolbar(currentPri
maryColor); |
| 1787 mUnfocusedLocationBarUsesTransparentBg = |
| 1788 !BrandColorUtils.shouldUseOpaqueTextboxBackground(currentPri
maryColor); |
| 1789 mUrlBackgroundAlpha = mUnfocusedLocationBarUsesTransparentBg |
| 1790 ? LOCATION_BAR_TRANSPARENT_BACKGROUND_ALPHA : 255; |
| 1791 progressBarResource = mUseLightToolbarDrawables |
| 1792 ? R.drawable.progress_bar_white : R.drawable.progress_bar; |
| 1793 } else { |
| 1794 mUseLightToolbarDrawables = false; |
| 1795 mUrlBackgroundAlpha = 255; |
| 1796 progressBarResource = R.drawable.progress_bar; |
| 1797 } |
| 1798 |
| 1799 getProgressBar().setProgressDrawable( |
| 1800 ApiCompatibilityUtils.getDrawable(getResources(), progressBarRes
ource)); |
| 1801 |
| 1802 mToggleTabStackButton.setImageDrawable(mUseLightToolbarDrawables |
| 1803 ? mTabSwitcherButtonDrawableLight : mTabSwitcherButtonDrawable); |
| 1804 |
| 1805 |
| 1806 ColorStateList dark = getResources().getColorStateList(R.color.dark_mode
_tint); |
| 1807 ColorStateList white = getResources().getColorStateList(R.color.light_mo
de_tint); |
| 1808 if (shouldShowMenuButton()) { |
| 1809 mMenuButton.setTint(mUseLightToolbarDrawables ? white : dark); |
| 1810 } |
| 1811 if (mHomeButton.getVisibility() != GONE) { |
| 1812 mHomeButton.setTint(mUseLightToolbarDrawables ? white : dark); |
| 1813 } |
| 1814 |
| 1815 mPhoneLocationBar.updateVisualsForState(); |
| 1816 |
| 1817 // We update the alpha before comparing the visual state as we need to c
hange |
| 1818 // it's value when entering and exiting TabSwitcher mode. |
| 1819 if (isLocationBarShownInNTP() && !isInTabSwitcherMode) { |
| 1820 updateNtpTransitionAnimation( |
| 1821 getToolbarDataProvider().getNewTabPageForCurrentTab()); |
| 1822 } |
| 1823 |
| 1824 if (isInTabSwitcherMode) mNewTabButton.setIsIncognito(isIncognito); |
| 1825 |
| 1826 CharSequence newTabContentDescription = getResources().getText( |
| 1827 isIncognito ? R.string.accessibility_toolbar_btn_new_incognito_t
ab : |
| 1828 R.string.accessibility_toolbar_btn_new_tab); |
| 1829 if (!newTabContentDescription.equals(mNewTabButton.getContentDescription
())) { |
| 1830 mNewTabButton.setContentDescription(newTabContentDescription); |
| 1831 } |
| 1832 } |
| 1833 |
| 1834 @Override |
| 1835 public LocationBar getLocationBar() { |
| 1836 return mPhoneLocationBar; |
| 1837 } |
| 1838 } |
| 1839 |
OLD | NEW |