Commit a38381ed authored by ianwen's avatar ianwen Committed by Commit bot

CancelAwareAnimatorListener and Refactor Custom Tab Toolbar Animation

This CL does two things.
1. Introduce CancelAwareAnimatorListener to Chrome. For vanilla
AnimationListener in Android, onAnimationCancel() and onAnimationEnd()
will both be called if Animator is canclled. This is a confusing
behavior and it caused problems in various places.
2. Change the way security icon animation works in custom tab, making
it able to refresh its theme when the color of the toolbar changes.

Credit of this CL goes to tedchoc@.

BUG=604520
R=tedchoc@chromium.org

Review-Url: https://codereview.chromium.org/2104053005
Cr-Commit-Position: refs/heads/master@{#402672}
parent 986d0c88
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:contentDescription="@string/accessibility_toolbar_btn_site_info" android:contentDescription="@string/accessibility_toolbar_btn_site_info"
android:scaleType="center" android:scaleType="center"
android:visibility="gone" /> android:visibility="invisible" />
<view <view
class="org.chromium.chrome.browser.toolbar.CustomTabToolbar$InterceptTouchLayout" class="org.chromium.chrome.browser.toolbar.CustomTabToolbar$InterceptTouchLayout"
android:id="@+id/title_url_container" android:id="@+id/title_url_container"
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
package org.chromium.chrome.browser.ntp.snippets; package org.chromium.chrome.browser.ntp.snippets;
import android.animation.Animator; import android.animation.Animator;
import android.animation.Animator.AnimatorListener; import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator; import android.animation.ObjectAnimator;
import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater; import android.view.LayoutInflater;
...@@ -92,17 +92,11 @@ public class SnippetHeaderViewHolder extends NewTabPageViewHolder { ...@@ -92,17 +92,11 @@ public class SnippetHeaderViewHolder extends NewTabPageViewHolder {
mAnimator = ObjectAnimator.ofFloat(itemView, View.ALPHA, currentAlpha, targetAlpha); mAnimator = ObjectAnimator.ofFloat(itemView, View.ALPHA, currentAlpha, targetAlpha);
mAnimator.setDuration(ANIMATION_DURATION_MS); mAnimator.setDuration(ANIMATION_DURATION_MS);
mAnimator.addListener(new AnimatorListener() { mAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animator) {}
@Override
public void onAnimationRepeat(Animator animator) {}
@Override @Override
public void onAnimationEnd(Animator animator) { public void onAnimationEnd(Animator animator) {
mAnimator = null; mAnimator = null;
} }
@Override
public void onAnimationCancel(Animator animator) {}
}); });
mAnimator.start(); mAnimator.start();
} }
......
...@@ -90,6 +90,7 @@ import org.chromium.chrome.browser.util.KeyNavigationUtil; ...@@ -90,6 +90,7 @@ import org.chromium.chrome.browser.util.KeyNavigationUtil;
import org.chromium.chrome.browser.util.ViewUtils; import org.chromium.chrome.browser.util.ViewUtils;
import org.chromium.chrome.browser.widget.TintedImageButton; import org.chromium.chrome.browser.widget.TintedImageButton;
import org.chromium.chrome.browser.widget.animation.AnimatorProperties; import org.chromium.chrome.browser.widget.animation.AnimatorProperties;
import org.chromium.chrome.browser.widget.animation.CancelAwareAnimatorListener;
import org.chromium.components.security_state.ConnectionSecurityLevel; import org.chromium.components.security_state.ConnectionSecurityLevel;
import org.chromium.content_public.browser.LoadUrlParams; import org.chromium.content_public.browser.LoadUrlParams;
import org.chromium.content_public.browser.WebContents; import org.chromium.content_public.browser.WebContents;
...@@ -2215,22 +2216,9 @@ public class LocationBarLayout extends FrameLayout implements OnClickListener, ...@@ -2215,22 +2216,9 @@ public class LocationBarLayout extends FrameLayout implements OnClickListener,
mFadeOutOmniboxBackgroundAnimator.setDuration(OMNIBOX_CONTAINER_BACKGROUND_FADE_MS); mFadeOutOmniboxBackgroundAnimator.setDuration(OMNIBOX_CONTAINER_BACKGROUND_FADE_MS);
mFadeOutOmniboxBackgroundAnimator.setInterpolator( mFadeOutOmniboxBackgroundAnimator.setInterpolator(
BakedBezierInterpolator.FADE_OUT_CURVE); BakedBezierInterpolator.FADE_OUT_CURVE);
mFadeOutOmniboxBackgroundAnimator.addListener(new AnimatorListenerAdapter() { mFadeOutOmniboxBackgroundAnimator.addListener(new CancelAwareAnimatorListener() {
private boolean mIsCancelled;
@Override
public void onAnimationStart(Animator animation) {
mIsCancelled = false;
}
@Override
public void onAnimationCancel(Animator animation) {
mIsCancelled = true;
}
@Override @Override
public void onAnimationEnd(Animator animation) { public void onEnd(Animator animator) {
if (mIsCancelled) return;
updateOmniboxResultsContainerVisibility(false); updateOmniboxResultsContainerVisibility(false);
} }
}); });
......
...@@ -387,11 +387,7 @@ public class LocationBarPhone extends LocationBarLayout { ...@@ -387,11 +387,7 @@ public class LocationBarPhone extends LocationBarLayout {
@Override @Override
public void onAnimationEnd(Animator animation) { public void onAnimationEnd(Animator animation) {
mIsMenuBadgeAnimationRunning = false; // animator#cancel() will trigger onAnimationEnd() as well.
}
@Override
public void onAnimationCancel(Animator animation) {
mIsMenuBadgeAnimationRunning = false; mIsMenuBadgeAnimationRunning = false;
} }
}); });
......
...@@ -20,6 +20,7 @@ import org.chromium.base.ApiCompatibilityUtils; ...@@ -20,6 +20,7 @@ import org.chromium.base.ApiCompatibilityUtils;
import org.chromium.chrome.R; import org.chromium.chrome.R;
import org.chromium.chrome.browser.ntp.NewTabPage; import org.chromium.chrome.browser.ntp.NewTabPage;
import org.chromium.chrome.browser.toolbar.ToolbarTablet; import org.chromium.chrome.browser.toolbar.ToolbarTablet;
import org.chromium.chrome.browser.widget.animation.CancelAwareAnimatorListener;
import org.chromium.ui.UiUtils; import org.chromium.ui.UiUtils;
import org.chromium.ui.base.LocalizationUtils; import org.chromium.ui.base.LocalizationUtils;
import org.chromium.ui.interpolators.BakedBezierInterpolator; import org.chromium.ui.interpolators.BakedBezierInterpolator;
...@@ -188,21 +189,15 @@ public class LocationBarTablet extends LocationBarLayout { ...@@ -188,21 +189,15 @@ public class LocationBarTablet extends LocationBarLayout {
ObjectAnimator.ofFloat(this, mUrlFocusChangePercentProperty, hasFocus ? 1f : 0f); ObjectAnimator.ofFloat(this, mUrlFocusChangePercentProperty, hasFocus ? 1f : 0f);
mUrlFocusChangeAnimator.setDuration( mUrlFocusChangeAnimator.setDuration(
(long) (MAX_NTP_KEYBOARD_FOCUS_DURATION_MS * screenSizeRatio)); (long) (MAX_NTP_KEYBOARD_FOCUS_DURATION_MS * screenSizeRatio));
mUrlFocusChangeAnimator.addListener(new AnimatorListenerAdapter() { mUrlFocusChangeAnimator.addListener(new CancelAwareAnimatorListener() {
private boolean mIsCancelled;
@Override @Override
public void onAnimationCancel(Animator animation) { public void onEnd(Animator animator) {
mIsCancelled = true; finishUrlFocusChange(hasFocus);
} }
@Override @Override
public void onAnimationEnd(Animator animation) { public void onCancel(Animator animator) {
if (mIsCancelled) { setUrlFocusChangeInProgress(false);
setUrlFocusChangeInProgress(false);
return;
}
finishUrlFocusChange(hasFocus);
} }
}); });
setUrlFocusChangeInProgress(true); setUrlFocusChangeInProgress(true);
......
...@@ -473,7 +473,7 @@ public class CustomTabToolbar extends ToolbarLayout implements LocationBar, ...@@ -473,7 +473,7 @@ public class CustomTabToolbar extends ToolbarLayout implements LocationBar,
@Override @Override
public void updateSecurityIcon(int securityLevel) { public void updateSecurityIcon(int securityLevel) {
if (mSecurityIconType == securityLevel || mState == STATE_TITLE_ONLY) return; if (mState == STATE_TITLE_ONLY) return;
mSecurityIconType = securityLevel; mSecurityIconType = securityLevel;
......
...@@ -14,6 +14,7 @@ import android.view.View; ...@@ -14,6 +14,7 @@ import android.view.View;
import android.widget.TextView; import android.widget.TextView;
import org.chromium.chrome.R; import org.chromium.chrome.R;
import org.chromium.chrome.browser.widget.animation.CancelAwareAnimatorListener;
import org.chromium.ui.interpolators.BakedBezierInterpolator; import org.chromium.ui.interpolators.BakedBezierInterpolator;
/** /**
...@@ -39,6 +40,7 @@ class CustomTabToolbarAnimationDelegate { ...@@ -39,6 +40,7 @@ class CustomTabToolbarAnimationDelegate {
private TextView mUrlBar; private TextView mUrlBar;
private TextView mTitleBar; private TextView mTitleBar;
private int mSecurityButtonWidth;
// A flag controlling whether the animation has run before. // A flag controlling whether the animation has run before.
private boolean mShouldRunTitleAnimation; private boolean mShouldRunTitleAnimation;
...@@ -48,44 +50,43 @@ class CustomTabToolbarAnimationDelegate { ...@@ -48,44 +50,43 @@ class CustomTabToolbarAnimationDelegate {
CustomTabToolbarAnimationDelegate(View securityButton, final View titleUrlContainer) { CustomTabToolbarAnimationDelegate(View securityButton, final View titleUrlContainer) {
mSecurityButton = securityButton; mSecurityButton = securityButton;
mTitleUrlContainer = titleUrlContainer; mTitleUrlContainer = titleUrlContainer;
mSecurityButtonWidth = securityButton.getResources()
.getDimensionPixelSize(R.dimen.location_bar_icon_width);
titleUrlContainer.setTranslationX(-mSecurityButtonWidth);
mSecurityButtonShowAnimator = new AnimatorSet(); mSecurityButtonShowAnimator = new AnimatorSet();
int securityButtonWidth = securityButton.getResources()
.getDimensionPixelSize(R.dimen.location_bar_icon_width);
Animator translateRight = ObjectAnimator.ofFloat(titleUrlContainer, Animator translateRight = ObjectAnimator.ofFloat(titleUrlContainer,
View.TRANSLATION_X, securityButtonWidth); View.TRANSLATION_X, 0);
translateRight.setInterpolator(BakedBezierInterpolator.TRANSFORM_CURVE); translateRight.setInterpolator(BakedBezierInterpolator.TRANSFORM_CURVE);
translateRight.setDuration(CUSTOM_TAB_TOOLBAR_SLIDE_DURATION_MS); translateRight.setDuration(CUSTOM_TAB_TOOLBAR_SLIDE_DURATION_MS);
Animator fadeIn = ObjectAnimator.ofFloat(mSecurityButton, View.ALPHA, 1); Animator fadeIn = ObjectAnimator.ofFloat(mSecurityButton, View.ALPHA, 1);
fadeIn.addListener(new AnimatorListenerAdapter() { fadeIn.setInterpolator(BakedBezierInterpolator.FADE_IN_CURVE);
fadeIn.setDuration(CUSTOM_TAB_TOOLBAR_FADE_DURATION_MS);
fadeIn.addListener(new CancelAwareAnimatorListener() {
@Override @Override
public void onAnimationStart(Animator animation) { public void onStart(Animator animation) {
mSecurityButton.setVisibility(View.VISIBLE); mSecurityButton.setVisibility(View.VISIBLE);
mSecurityButton.setAlpha(0f);
titleUrlContainer.setTranslationX(0);
} }
}); });
fadeIn.setInterpolator(BakedBezierInterpolator.FADE_IN_CURVE);
fadeIn.setDuration(CUSTOM_TAB_TOOLBAR_FADE_DURATION_MS);
mSecurityButtonShowAnimator.playSequentially(translateRight, fadeIn); mSecurityButtonShowAnimator.playSequentially(translateRight, fadeIn);
mSecurityButtonHideAnimator = new AnimatorSet(); mSecurityButtonHideAnimator = new AnimatorSet();
Animator fadeOut = ObjectAnimator.ofFloat(mSecurityButton, View.ALPHA, 0); Animator fadeOut = ObjectAnimator.ofFloat(mSecurityButton, View.ALPHA, 0);
fadeOut.setInterpolator(BakedBezierInterpolator.FADE_OUT_CURVE); fadeOut.setInterpolator(BakedBezierInterpolator.FADE_OUT_CURVE);
fadeOut.setDuration(CUSTOM_TAB_TOOLBAR_FADE_DURATION_MS); fadeOut.setDuration(CUSTOM_TAB_TOOLBAR_FADE_DURATION_MS);
fadeOut.addListener(new CancelAwareAnimatorListener() {
@Override
public void onEnd(Animator animation) {
mSecurityButton.setVisibility(View.INVISIBLE);
}
});
Animator translateLeft = ObjectAnimator.ofFloat(titleUrlContainer, Animator translateLeft = ObjectAnimator.ofFloat(titleUrlContainer,
View.TRANSLATION_X, -securityButtonWidth); View.TRANSLATION_X, -mSecurityButtonWidth);
translateLeft.setInterpolator(BakedBezierInterpolator.TRANSFORM_CURVE); translateLeft.setInterpolator(BakedBezierInterpolator.TRANSFORM_CURVE);
translateLeft.setDuration(CUSTOM_TAB_TOOLBAR_SLIDE_DURATION_MS); translateLeft.setDuration(CUSTOM_TAB_TOOLBAR_SLIDE_DURATION_MS);
translateLeft.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
mSecurityButton.setVisibility(View.GONE);
titleUrlContainer.setTranslationX(0);
}
});
mSecurityButtonHideAnimator.playSequentially(fadeOut, translateLeft); mSecurityButtonHideAnimator.playSequentially(fadeOut, translateLeft);
} }
...@@ -160,7 +161,11 @@ class CustomTabToolbarAnimationDelegate { ...@@ -160,7 +161,11 @@ class CustomTabToolbarAnimationDelegate {
* Starts the animation to show the security button. * Starts the animation to show the security button.
*/ */
void showSecurityButton() { void showSecurityButton() {
if (mSecurityButtonShowAnimator.isStarted()) return; if (mSecurityButtonHideAnimator.isStarted()) mSecurityButtonHideAnimator.cancel();
if (mSecurityButtonShowAnimator.isStarted()
|| mSecurityButton.getVisibility() == View.VISIBLE) {
return;
}
mSecurityButtonShowAnimator.start(); mSecurityButtonShowAnimator.start();
} }
...@@ -168,14 +173,11 @@ class CustomTabToolbarAnimationDelegate { ...@@ -168,14 +173,11 @@ class CustomTabToolbarAnimationDelegate {
* Starts the animation to hide the security button. * Starts the animation to hide the security button.
*/ */
void hideSecurityButton() { void hideSecurityButton() {
// An optimization for the case that show and hide are called almost at the same time. if (mSecurityButtonShowAnimator.isStarted()) mSecurityButtonShowAnimator.cancel();
if (mSecurityButtonShowAnimator.isStarted() if (mSecurityButtonHideAnimator.isStarted()
&& mSecurityButton.getVisibility() == View.GONE) { || mTitleUrlContainer.getTranslationX() == -mSecurityButtonWidth) {
mSecurityButtonShowAnimator.cancel();
mTitleUrlContainer.setTranslationX(0);
return; return;
} }
if (mSecurityButtonHideAnimator.isStarted()) return;
mSecurityButtonHideAnimator.start(); mSecurityButtonHideAnimator.start();
} }
} }
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser.widget.animation;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
/**
* An {@link AnimatorListenerAdapter} that distinguishes cancel and end signal. Subclasses should
* override {@link #onStart(Animator)}, {@link #onEnd(Animator)} and {@link #onCancel(Animator)}
* instead of the standard callback functions.
*/
public class CancelAwareAnimatorListener extends AnimatorListenerAdapter {
private boolean mIsCancelled;
@Override
public final void onAnimationStart(Animator animation) {
mIsCancelled = false;
onStart(animation);
}
@Override
public final void onAnimationCancel(Animator animation) {
mIsCancelled = true;
onCancel(animation);
}
@Override
public final void onAnimationEnd(Animator animation) {
if (mIsCancelled) return;
onEnd(animation);
}
/**
* Notifies the start of the animator.
*/
public void onStart(Animator animator) { }
/**
* Notifies that the animator was cancelled.
*/
public void onCancel(Animator animator) { }
/**
* Notifies that the animator has finished running. This method will not be called if the
* animator is canclled.
*/
public void onEnd(Animator animator) { }
}
...@@ -958,6 +958,7 @@ chrome_java_sources = [ ...@@ -958,6 +958,7 @@ chrome_java_sources = [
"java/src/org/chromium/chrome/browser/widget/accessibility/AccessibilityTabModelListView.java", "java/src/org/chromium/chrome/browser/widget/accessibility/AccessibilityTabModelListView.java",
"java/src/org/chromium/chrome/browser/widget/accessibility/AccessibilityTabModelWrapper.java", "java/src/org/chromium/chrome/browser/widget/accessibility/AccessibilityTabModelWrapper.java",
"java/src/org/chromium/chrome/browser/widget/animation/AnimatorProperties.java", "java/src/org/chromium/chrome/browser/widget/animation/AnimatorProperties.java",
"java/src/org/chromium/chrome/browser/widget/animation/CancelAwareAnimatorListener.java",
"java/src/org/chromium/chrome/browser/widget/animation/FocusAnimator.java", "java/src/org/chromium/chrome/browser/widget/animation/FocusAnimator.java",
"java/src/org/chromium/chrome/browser/widget/emptybackground/EmptyBackgroundViewTablet.java", "java/src/org/chromium/chrome/browser/widget/emptybackground/EmptyBackgroundViewTablet.java",
"java/src/org/chromium/chrome/browser/widget/emptybackground/EmptyBackgroundViewWrapper.java", "java/src/org/chromium/chrome/browser/widget/emptybackground/EmptyBackgroundViewWrapper.java",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment