Index: chrome/android/java/src/org/chromium/chrome/browser/appmenu/IconHighlightDrawable.java |
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/IconHighlightDrawable.java b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/IconHighlightDrawable.java |
new file mode 100644 |
index 0000000000000000000000000000000000000000..366f8b2b581ca1dbc9915cb48fd15b7ca092ea56 |
--- /dev/null |
+++ b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/IconHighlightDrawable.java |
@@ -0,0 +1,115 @@ |
+// Copyright 2017 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.appmenu; |
+ |
+import android.animation.Animator; |
+import android.animation.AnimatorListenerAdapter; |
+import android.animation.AnimatorSet; |
+import android.animation.ObjectAnimator; |
+import android.graphics.Canvas; |
+import android.graphics.Rect; |
+import android.graphics.drawable.Drawable; |
+import android.graphics.drawable.ShapeDrawable; |
+import android.graphics.drawable.shapes.OvalShape; |
+import android.support.annotation.ColorRes; |
+import android.support.v4.view.animation.PathInterpolatorCompat; |
+ |
+/** A {@link Drawable} that draws a circular pulsing dot. */ |
+public class IconHighlightDrawable extends ShapeDrawable { |
+ private final Rect mCacheRect = new Rect(); |
+ private final Rect mMargin = new Rect(); |
+ private float mScale; |
+ |
+ /** |
+ * Creates a new {@link IconHighlightDrawable} with the specified color. |
+ * @param color The color to make the {@link Drawable}. |
+ */ |
+ public IconHighlightDrawable(@ColorRes int color) { |
+ setShape(new OvalShape()); |
+ setAlpha(75); |
+ getPaint().setColor(color); |
+ startAnimation(); |
+ } |
+ |
+ @Override |
+ public void draw(Canvas canvas) { |
+ canvas.save(); |
+ canvas.scale(mScale, mScale, getBounds().exactCenterX(), getBounds().exactCenterY()); |
+ super.draw(canvas); |
+ canvas.restore(); |
+ } |
+ |
+ @Override |
+ public void setBounds(Rect bounds) { |
+ mCacheRect.set(bounds.left + mMargin.left, bounds.top + mMargin.top, |
+ bounds.right - mMargin.right, bounds.bottom - mMargin.bottom); |
+ makeSquare(mCacheRect); |
+ super.setBounds(mCacheRect); |
+ } |
+ |
+ @Override |
+ public void setBounds(int left, int top, int right, int bottom) { |
+ mCacheRect.set(left + mMargin.left, top + mMargin.top, right - mMargin.right, |
+ bottom - mMargin.bottom); |
+ makeSquare(mCacheRect); |
+ super.setBounds(mCacheRect.left, mCacheRect.top, mCacheRect.right, mCacheRect.bottom); |
+ } |
+ |
+ /** How much to inset the {@link Drawable} bounds by. */ |
+ public void setMargin(int left, int top, int right, int bottom) { |
+ mMargin.set(left, top, right, bottom); |
+ setBounds(getBounds()); |
+ } |
+ |
+ /** |
+ * Sets the scale of the circle this {@link Drawable} draws. |
+ * @param scale The scale (from 0.f to 1.f). |
+ */ |
+ public void setScale(float scale) { |
+ mScale = scale; |
+ invalidateSelf(); |
+ } |
+ |
+ private void startAnimation() { |
+ final float minScale = 0.8f; |
+ final float maxScale = 1.f; |
+ setScale(minScale); |
+ ObjectAnimator scaleUpAnim = ObjectAnimator.ofFloat(this, "scale", minScale, maxScale); |
+ scaleUpAnim.setStartDelay(500); |
+ scaleUpAnim.setDuration(500); |
+ scaleUpAnim.setInterpolator(PathInterpolatorCompat.create(.8f, 0.f, .6f, 1.f)); |
+ |
+ ObjectAnimator scaleDownAnim = ObjectAnimator.ofFloat(this, "scale", maxScale, minScale); |
+ scaleDownAnim.setDuration(250); |
+ scaleDownAnim.setInterpolator(PathInterpolatorCompat.create(.8f, 0.f, .6f, 1.f)); |
+ |
+ AnimatorSet set = new AnimatorSet(); |
+ set.playSequentially(scaleUpAnim, scaleDownAnim); |
+ set.addListener(new AnimatorListenerAdapter() { |
+ private boolean mCanceled; |
+ |
+ @Override |
+ public void onAnimationStart(Animator animation) { |
+ mCanceled = false; |
+ } |
+ |
+ @Override |
+ public void onAnimationCancel(Animator animation) { |
+ mCanceled = true; |
+ } |
+ |
+ @Override |
+ public void onAnimationEnd(Animator animation) { |
+ if (!mCanceled) animation.start(); |
+ } |
+ }); |
+ set.start(); |
+ } |
+ |
+ private void makeSquare(Rect rect) { |
+ int minDimension = Math.min(rect.width(), rect.height()); |
+ rect.inset((rect.width() - minDimension) / 2, (rect.height() - minDimension) / 2); |
+ } |
+} |