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 @@
android:layout_gravity="center_vertical"
android:contentDescription="@string/accessibility_toolbar_btn_site_info"
android:scaleType="center"
android:visibility="gone" />
android:visibility="invisible" />
<view
class="org.chromium.chrome.browser.toolbar.CustomTabToolbar$InterceptTouchLayout"
android:id="@+id/title_url_container"
......
......@@ -5,7 +5,7 @@
package org.chromium.chrome.browser.ntp.snippets;
import android.animation.Animator;
import android.animation.Animator.AnimatorListener;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
......@@ -92,17 +92,11 @@ public class SnippetHeaderViewHolder extends NewTabPageViewHolder {
mAnimator = ObjectAnimator.ofFloat(itemView, View.ALPHA, currentAlpha, targetAlpha);
mAnimator.setDuration(ANIMATION_DURATION_MS);
mAnimator.addListener(new AnimatorListener() {
@Override
public void onAnimationStart(Animator animator) {}
@Override
public void onAnimationRepeat(Animator animator) {}
mAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animator) {
mAnimator = null;
}
@Override
public void onAnimationCancel(Animator animator) {}
});
mAnimator.start();
}
......
......@@ -90,6 +90,7 @@ import org.chromium.chrome.browser.util.KeyNavigationUtil;
import org.chromium.chrome.browser.util.ViewUtils;
import org.chromium.chrome.browser.widget.TintedImageButton;
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.content_public.browser.LoadUrlParams;
import org.chromium.content_public.browser.WebContents;
......@@ -2215,22 +2216,9 @@ public class LocationBarLayout extends FrameLayout implements OnClickListener,
mFadeOutOmniboxBackgroundAnimator.setDuration(OMNIBOX_CONTAINER_BACKGROUND_FADE_MS);
mFadeOutOmniboxBackgroundAnimator.setInterpolator(
BakedBezierInterpolator.FADE_OUT_CURVE);
mFadeOutOmniboxBackgroundAnimator.addListener(new AnimatorListenerAdapter() {
private boolean mIsCancelled;
@Override
public void onAnimationStart(Animator animation) {
mIsCancelled = false;
}
@Override
public void onAnimationCancel(Animator animation) {
mIsCancelled = true;
}
mFadeOutOmniboxBackgroundAnimator.addListener(new CancelAwareAnimatorListener() {
@Override
public void onAnimationEnd(Animator animation) {
if (mIsCancelled) return;
public void onEnd(Animator animator) {
updateOmniboxResultsContainerVisibility(false);
}
});
......
......@@ -387,11 +387,7 @@ public class LocationBarPhone extends LocationBarLayout {
@Override
public void onAnimationEnd(Animator animation) {
mIsMenuBadgeAnimationRunning = false;
}
@Override
public void onAnimationCancel(Animator animation) {
// animator#cancel() will trigger onAnimationEnd() as well.
mIsMenuBadgeAnimationRunning = false;
}
});
......
......@@ -20,6 +20,7 @@ import org.chromium.base.ApiCompatibilityUtils;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.ntp.NewTabPage;
import org.chromium.chrome.browser.toolbar.ToolbarTablet;
import org.chromium.chrome.browser.widget.animation.CancelAwareAnimatorListener;
import org.chromium.ui.UiUtils;
import org.chromium.ui.base.LocalizationUtils;
import org.chromium.ui.interpolators.BakedBezierInterpolator;
......@@ -188,21 +189,15 @@ public class LocationBarTablet extends LocationBarLayout {
ObjectAnimator.ofFloat(this, mUrlFocusChangePercentProperty, hasFocus ? 1f : 0f);
mUrlFocusChangeAnimator.setDuration(
(long) (MAX_NTP_KEYBOARD_FOCUS_DURATION_MS * screenSizeRatio));
mUrlFocusChangeAnimator.addListener(new AnimatorListenerAdapter() {
private boolean mIsCancelled;
mUrlFocusChangeAnimator.addListener(new CancelAwareAnimatorListener() {
@Override
public void onAnimationCancel(Animator animation) {
mIsCancelled = true;
public void onEnd(Animator animator) {
finishUrlFocusChange(hasFocus);
}
@Override
public void onAnimationEnd(Animator animation) {
if (mIsCancelled) {
setUrlFocusChangeInProgress(false);
return;
}
finishUrlFocusChange(hasFocus);
public void onCancel(Animator animator) {
setUrlFocusChangeInProgress(false);
}
});
setUrlFocusChangeInProgress(true);
......
......@@ -473,7 +473,7 @@ public class CustomTabToolbar extends ToolbarLayout implements LocationBar,
@Override
public void updateSecurityIcon(int securityLevel) {
if (mSecurityIconType == securityLevel || mState == STATE_TITLE_ONLY) return;
if (mState == STATE_TITLE_ONLY) return;
mSecurityIconType = securityLevel;
......
......@@ -14,6 +14,7 @@ import android.view.View;
import android.widget.TextView;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.widget.animation.CancelAwareAnimatorListener;
import org.chromium.ui.interpolators.BakedBezierInterpolator;
/**
......@@ -39,6 +40,7 @@ class CustomTabToolbarAnimationDelegate {
private TextView mUrlBar;
private TextView mTitleBar;
private int mSecurityButtonWidth;
// A flag controlling whether the animation has run before.
private boolean mShouldRunTitleAnimation;
......@@ -48,44 +50,43 @@ class CustomTabToolbarAnimationDelegate {
CustomTabToolbarAnimationDelegate(View securityButton, final View titleUrlContainer) {
mSecurityButton = securityButton;
mTitleUrlContainer = titleUrlContainer;
mSecurityButtonWidth = securityButton.getResources()
.getDimensionPixelSize(R.dimen.location_bar_icon_width);
titleUrlContainer.setTranslationX(-mSecurityButtonWidth);
mSecurityButtonShowAnimator = new AnimatorSet();
int securityButtonWidth = securityButton.getResources()
.getDimensionPixelSize(R.dimen.location_bar_icon_width);
Animator translateRight = ObjectAnimator.ofFloat(titleUrlContainer,
View.TRANSLATION_X, securityButtonWidth);
View.TRANSLATION_X, 0);
translateRight.setInterpolator(BakedBezierInterpolator.TRANSFORM_CURVE);
translateRight.setDuration(CUSTOM_TAB_TOOLBAR_SLIDE_DURATION_MS);
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
public void onAnimationStart(Animator animation) {
public void onStart(Animator animation) {
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);
mSecurityButtonHideAnimator = new AnimatorSet();
Animator fadeOut = ObjectAnimator.ofFloat(mSecurityButton, View.ALPHA, 0);
fadeOut.setInterpolator(BakedBezierInterpolator.FADE_OUT_CURVE);
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,
View.TRANSLATION_X, -securityButtonWidth);
View.TRANSLATION_X, -mSecurityButtonWidth);
translateLeft.setInterpolator(BakedBezierInterpolator.TRANSFORM_CURVE);
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);
}
......@@ -160,7 +161,11 @@ class CustomTabToolbarAnimationDelegate {
* Starts the animation to show the security button.
*/
void showSecurityButton() {
if (mSecurityButtonShowAnimator.isStarted()) return;
if (mSecurityButtonHideAnimator.isStarted()) mSecurityButtonHideAnimator.cancel();
if (mSecurityButtonShowAnimator.isStarted()
|| mSecurityButton.getVisibility() == View.VISIBLE) {
return;
}
mSecurityButtonShowAnimator.start();
}
......@@ -168,14 +173,11 @@ class CustomTabToolbarAnimationDelegate {
* Starts the animation to hide the security button.
*/
void hideSecurityButton() {
// An optimization for the case that show and hide are called almost at the same time.
if (mSecurityButtonShowAnimator.isStarted()
&& mSecurityButton.getVisibility() == View.GONE) {
mSecurityButtonShowAnimator.cancel();
mTitleUrlContainer.setTranslationX(0);
if (mSecurityButtonShowAnimator.isStarted()) mSecurityButtonShowAnimator.cancel();
if (mSecurityButtonHideAnimator.isStarted()
|| mTitleUrlContainer.getTranslationX() == -mSecurityButtonWidth) {
return;
}
if (mSecurityButtonHideAnimator.isStarted()) return;
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 = [
"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/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/emptybackground/EmptyBackgroundViewTablet.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