summaryrefslogtreecommitdiffstats
path: root/src/com/android/launcher3/popup/PopupItemView.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/launcher3/popup/PopupItemView.java')
-rw-r--r--src/com/android/launcher3/popup/PopupItemView.java208
1 files changed, 208 insertions, 0 deletions
diff --git a/src/com/android/launcher3/popup/PopupItemView.java b/src/com/android/launcher3/popup/PopupItemView.java
new file mode 100644
index 000000000..25d496a4b
--- /dev/null
+++ b/src/com/android/launcher3/popup/PopupItemView.java
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.popup;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
+import android.content.Context;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.FrameLayout;
+
+import com.android.launcher3.LogAccelerateInterpolator;
+import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.util.PillRevealOutlineProvider;
+import com.android.launcher3.util.PillWidthRevealOutlineProvider;
+
+/**
+ * An abstract {@link FrameLayout} that supports animating an item's content
+ * (e.g. icon and text) separate from the item's background.
+ */
+public abstract class PopupItemView extends FrameLayout
+ implements ValueAnimator.AnimatorUpdateListener {
+
+ protected static final Point sTempPoint = new Point();
+
+ private final Rect mPillRect;
+ private float mOpenAnimationProgress;
+
+ protected View mIconView;
+
+ public PopupItemView(Context context) {
+ this(context, null, 0);
+ }
+
+ public PopupItemView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public PopupItemView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+
+ mPillRect = new Rect();
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ mIconView = findViewById(R.id.popup_item_icon);
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ mPillRect.set(0, 0, getMeasuredWidth(), getMeasuredHeight());
+ }
+
+ public boolean willDrawIcon() {
+ return true;
+ }
+
+ /**
+ * Creates an animator to play when the shortcut container is being opened.
+ */
+ public Animator createOpenAnimation(boolean isContainerAboveIcon, boolean pivotLeft) {
+ Point center = getIconCenter();
+ ValueAnimator openAnimator = new ZoomRevealOutlineProvider(center.x, center.y,
+ mPillRect, this, mIconView, isContainerAboveIcon, pivotLeft)
+ .createRevealAnimator(this, false);
+ mOpenAnimationProgress = 0f;
+ openAnimator.addUpdateListener(this);
+ return openAnimator;
+ }
+
+ @Override
+ public void onAnimationUpdate(ValueAnimator valueAnimator) {
+ mOpenAnimationProgress = valueAnimator.getAnimatedFraction();
+ }
+
+ public boolean isOpenOrOpening() {
+ return mOpenAnimationProgress > 0;
+ }
+
+ /**
+ * Creates an animator to play when the shortcut container is being closed.
+ */
+ public Animator createCloseAnimation(boolean isContainerAboveIcon, boolean pivotLeft,
+ long duration) {
+ Point center = getIconCenter();
+ ValueAnimator closeAnimator = new ZoomRevealOutlineProvider(center.x, center.y,
+ mPillRect, this, mIconView, isContainerAboveIcon, pivotLeft)
+ .createRevealAnimator(this, true);
+ // Scale down the duration and interpolator according to the progress
+ // that the open animation was at when the close started.
+ closeAnimator.setDuration((long) (duration * mOpenAnimationProgress));
+ closeAnimator.setInterpolator(new CloseInterpolator(mOpenAnimationProgress));
+ closeAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mOpenAnimationProgress = 0;
+ }
+ });
+ return closeAnimator;
+ }
+
+ /**
+ * Creates an animator which clips the container to form a circle around the icon.
+ */
+ public Animator collapseToIcon() {
+ int halfHeight = getMeasuredHeight() / 2;
+ int iconCenterX = getIconCenter().x;
+ return new PillWidthRevealOutlineProvider(mPillRect,
+ iconCenterX - halfHeight, iconCenterX + halfHeight)
+ .createRevealAnimator(this, true);
+ }
+
+ /**
+ * Returns the position of the center of the icon relative to the container.
+ */
+ public Point getIconCenter() {
+ sTempPoint.y = sTempPoint.x = getMeasuredHeight() / 2;
+ if (Utilities.isRtl(getResources())) {
+ sTempPoint.x = getMeasuredWidth() - sTempPoint.x;
+ }
+ return sTempPoint;
+ }
+
+ /**
+ * Extension of {@link PillRevealOutlineProvider} which scales the icon based on the height.
+ */
+ private static class ZoomRevealOutlineProvider extends PillRevealOutlineProvider {
+
+ private final View mTranslateView;
+ private final View mZoomView;
+
+ private final float mFullHeight;
+ private final float mTranslateYMultiplier;
+
+ private final boolean mPivotLeft;
+ private final float mTranslateX;
+
+ public ZoomRevealOutlineProvider(int x, int y, Rect pillRect,
+ View translateView, View zoomView, boolean isContainerAboveIcon, boolean pivotLeft) {
+ super(x, y, pillRect);
+ mTranslateView = translateView;
+ mZoomView = zoomView;
+ mFullHeight = pillRect.height();
+
+ mTranslateYMultiplier = isContainerAboveIcon ? 0.5f : -0.5f;
+
+ mPivotLeft = pivotLeft;
+ mTranslateX = pivotLeft ? pillRect.height() / 2 : pillRect.right - pillRect.height() / 2;
+ }
+
+ @Override
+ public void setProgress(float progress) {
+ super.setProgress(progress);
+
+ mZoomView.setScaleX(progress);
+ mZoomView.setScaleY(progress);
+
+ float height = mOutline.height();
+ mTranslateView.setTranslationY(mTranslateYMultiplier * (mFullHeight - height));
+
+ float pivotX = mPivotLeft ? (mOutline.left + height / 2) : (mOutline.right - height / 2);
+ mTranslateView.setTranslationX(mTranslateX - pivotX);
+ }
+ }
+
+ /**
+ * An interpolator that reverses the current open animation progress.
+ */
+ private static class CloseInterpolator extends LogAccelerateInterpolator {
+ private float mStartProgress;
+ private float mRemainingProgress;
+
+ /**
+ * @param openAnimationProgress The progress that the open interpolator ended at.
+ */
+ public CloseInterpolator(float openAnimationProgress) {
+ super(100, 0);
+ mStartProgress = 1f - openAnimationProgress;
+ mRemainingProgress = openAnimationProgress;
+ }
+
+ @Override
+ public float getInterpolation(float v) {
+ return mStartProgress + super.getInterpolation(v) * mRemainingProgress;
+ }
+ }
+}