// Copyright 2015 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.findinpage; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ObjectAnimator; import android.content.Context; import android.content.res.Resources; import android.graphics.Rect; import android.util.AttributeSet; import android.view.View; import android.view.animation.DecelerateInterpolator; import android.widget.FrameLayout; import org.chromium.chrome.R; /** * A tablet specific version of the {@link FindToolbar}. */ public class FindToolbarTablet extends FindToolbar { private static final int ENTER_EXIT_ANIMATION_DURATION_MS = 200; private static final int MAKE_ROOM_ANIMATION_DURATION_MS = 200; private static final float Y_INSET_DP = 8.f; private ObjectAnimator mCurrentAnimation; private ObjectAnimator mAnimationEnter; private ObjectAnimator mAnimationLeave; private final int mYInsetPx; /** * Creates an instance of a {@link FindToolbarTablet}. * @param context The Context to create the {@link FindToolbarTablet} under. * @param attrs The AttributeSet used to create the {@link FindToolbarTablet}. */ public FindToolbarTablet(Context context, AttributeSet attrs) { super(context, attrs); mYInsetPx = (int) (context.getResources().getDisplayMetrics().density * Y_INSET_DP); } @Override public void onFinishInflate() { super.onFinishInflate(); setVisibility(View.GONE); Resources resources = getContext().getResources(); int width = resources.getDimensionPixelSize(R.dimen.find_in_page_popup_width); int endMargin = resources.getDimensionPixelOffset(R.dimen.find_in_page_popup_margin_end); int translateWidth = width + endMargin; mAnimationEnter = ObjectAnimator.ofFloat(this, View.TRANSLATION_X, translateWidth, 0); mAnimationEnter.setDuration(ENTER_EXIT_ANIMATION_DURATION_MS); mAnimationEnter.setInterpolator(new DecelerateInterpolator()); mAnimationEnter.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animation) { setVisibility(View.VISIBLE); postInvalidateOnAnimation(); superActivate(); } @Override public void onAnimationEnd(Animator animation) { mCurrentAnimation = null; } }); mAnimationLeave = ObjectAnimator.ofFloat(this, View.TRANSLATION_X, 0, translateWidth); mAnimationLeave.setDuration(ENTER_EXIT_ANIMATION_DURATION_MS); mAnimationLeave.setInterpolator(new DecelerateInterpolator()); mAnimationLeave.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animation) { setVisibility(View.VISIBLE); postInvalidateOnAnimation(); } @Override public void onAnimationEnd(Animator animation) { setVisibility(View.GONE); mCurrentAnimation = null; } }); } @Override public void activate() { if (mCurrentAnimation == mAnimationEnter) return; if (isViewAvailable()) setShowState(true); } @Override public void deactivate(boolean clearSelection) { super.deactivate(clearSelection); if (mCurrentAnimation == mAnimationLeave) return; setShowState(false); } @Override public boolean isAnimating() { return mCurrentAnimation != null; } @Override public void findResultSelected(Rect rect) { super.findResultSelected(rect); boolean makeRoom = false; float density = getContext().getResources().getDisplayMetrics().density; if (rect != null && rect.intersects((int) (getLeft() / density), 0, (int) (getRight() / density), (int) (getHeight() / density))) { makeRoom = true; } setMakeRoomForResults(makeRoom); } @Override protected void clearResults() { super.clearResults(); setMakeRoomForResults(false); } private void setMakeRoomForResults(boolean makeRoom) { float translationY = makeRoom ? -(getHeight() - mYInsetPx) : 0.f; if (translationY != getTranslationY()) { mCurrentAnimation = ObjectAnimator.ofFloat(this, View.TRANSLATION_Y, translationY); mCurrentAnimation.setDuration(MAKE_ROOM_ANIMATION_DURATION_MS); mAnimationLeave.setInterpolator(new DecelerateInterpolator()); mAnimationLeave.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animation) { postInvalidateOnAnimation(); } @Override public void onAnimationEnd(Animator animation) { mCurrentAnimation = null; } }); startAnimationOverContent(mCurrentAnimation); } } private void setShowState(boolean show) { ObjectAnimator nextAnimator = null; if (show && getVisibility() != View.VISIBLE && mCurrentAnimation != mAnimationEnter) { View anchorView = getRootView().findViewById(R.id.toolbar); FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams(); lp.topMargin = anchorView.getBottom() - mYInsetPx; setLayoutParams(lp); nextAnimator = mAnimationEnter; } else if (!show && getVisibility() != View.GONE && mCurrentAnimation != mAnimationLeave) { nextAnimator = mAnimationLeave; onHideAnimationStart(); } if (nextAnimator != null) { mCurrentAnimation = nextAnimator; startAnimationOverContent(nextAnimator); postInvalidateOnAnimation(); } } /** * This is here so that Animation inner classes can access the parent activate methods. */ private void superActivate() { super.activate(); } }