11bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham/* 21bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham * Copyright (C) 2016 The Android Open Source Project 31bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham * 41bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham * Licensed under the Apache License, Version 2.0 (the "License"); 51bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham * you may not use this file except in compliance with the License. 61bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham * You may obtain a copy of the License at 71bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham * 81bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham * http://www.apache.org/licenses/LICENSE-2.0 91bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham * 101bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham * Unless required by applicable law or agreed to in writing, software 111bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham * distributed under the License is distributed on an "AS IS" BASIS, 121bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham * See the License for the specific language governing permissions and 141bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham * limitations under the License. 151bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham */ 161bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham 171bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickhampackage com.android.launcher3.shortcuts; 181bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham 198f58e61d02fcb0ca90a2803e76a8792ec2c1f99aTony Wickhamimport android.animation.Animator; 200ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickhamimport android.animation.ValueAnimator; 211bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickhamimport android.content.Context; 22a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyalimport android.graphics.Point; 238f58e61d02fcb0ca90a2803e76a8792ec2c1f99aTony Wickhamimport android.graphics.Rect; 245836bf728e85c1c4fae67862deb4e973ac55e944Sunny Goyalimport android.text.TextUtils; 251bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickhamimport android.util.AttributeSet; 26a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyalimport android.view.View; 278f58e61d02fcb0ca90a2803e76a8792ec2c1f99aTony Wickhamimport android.widget.FrameLayout; 281bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham 29a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyalimport com.android.launcher3.IconCache; 305836bf728e85c1c4fae67862deb4e973ac55e944Sunny Goyalimport com.android.launcher3.Launcher; 31a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyalimport com.android.launcher3.LauncherAppState; 320ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickhamimport com.android.launcher3.LogAccelerateInterpolator; 331bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickhamimport com.android.launcher3.R; 34a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyalimport com.android.launcher3.ShortcutInfo; 35a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyalimport com.android.launcher3.Utilities; 365836bf728e85c1c4fae67862deb4e973ac55e944Sunny Goyalimport com.android.launcher3.shortcuts.DeepShortcutsContainer.UnbadgedShortcutInfo; 378f58e61d02fcb0ca90a2803e76a8792ec2c1f99aTony Wickhamimport com.android.launcher3.util.PillRevealOutlineProvider; 38a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyalimport com.android.launcher3.util.PillWidthRevealOutlineProvider; 391bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham 401bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham/** 418f58e61d02fcb0ca90a2803e76a8792ec2c1f99aTony Wickham * A {@link android.widget.FrameLayout} that contains a {@link DeepShortcutView}. 428f58e61d02fcb0ca90a2803e76a8792ec2c1f99aTony Wickham * This lets us animate the DeepShortcutView (icon and text) separately from the background. 431bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham */ 440ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickhampublic class DeepShortcutView extends FrameLayout implements ValueAnimator.AnimatorUpdateListener { 458f58e61d02fcb0ca90a2803e76a8792ec2c1f99aTony Wickham 46a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal private static final Point sTempPoint = new Point(); 478f58e61d02fcb0ca90a2803e76a8792ec2c1f99aTony Wickham 48a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal private final Rect mPillRect; 49a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal 50a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal private DeepShortcutTextView mBubbleText; 51a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal private View mIconView; 520ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickham private float mOpenAnimationProgress; 531bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham 545836bf728e85c1c4fae67862deb4e973ac55e944Sunny Goyal private UnbadgedShortcutInfo mInfo; 555836bf728e85c1c4fae67862deb4e973ac55e944Sunny Goyal 561bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham public DeepShortcutView(Context context) { 571bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham this(context, null, 0); 581bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham } 591bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham 601bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham public DeepShortcutView(Context context, AttributeSet attrs) { 611bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham this(context, attrs, 0); 621bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham } 631bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham 641bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham public DeepShortcutView(Context context, AttributeSet attrs, int defStyle) { 651bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham super(context, attrs, defStyle); 661bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham 678f58e61d02fcb0ca90a2803e76a8792ec2c1f99aTony Wickham mPillRect = new Rect(); 688f58e61d02fcb0ca90a2803e76a8792ec2c1f99aTony Wickham } 698f58e61d02fcb0ca90a2803e76a8792ec2c1f99aTony Wickham 708f58e61d02fcb0ca90a2803e76a8792ec2c1f99aTony Wickham @Override 718f58e61d02fcb0ca90a2803e76a8792ec2c1f99aTony Wickham protected void onFinishInflate() { 728f58e61d02fcb0ca90a2803e76a8792ec2c1f99aTony Wickham super.onFinishInflate(); 73a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal mIconView = findViewById(R.id.deep_shortcut_icon); 74a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal mBubbleText = (DeepShortcutTextView) findViewById(R.id.deep_shortcut); 751bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham } 761bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham 77a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal public DeepShortcutTextView getBubbleText() { 788f58e61d02fcb0ca90a2803e76a8792ec2c1f99aTony Wickham return mBubbleText; 798f58e61d02fcb0ca90a2803e76a8792ec2c1f99aTony Wickham } 808f58e61d02fcb0ca90a2803e76a8792ec2c1f99aTony Wickham 81a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal public void setWillDrawIcon(boolean willDraw) { 82a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal mIconView.setVisibility(willDraw ? View.VISIBLE : View.INVISIBLE); 83a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal } 84a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal 85a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal public boolean willDrawIcon() { 86a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal return mIconView.getVisibility() == View.VISIBLE; 87a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal } 88a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal 898f58e61d02fcb0ca90a2803e76a8792ec2c1f99aTony Wickham @Override 908f58e61d02fcb0ca90a2803e76a8792ec2c1f99aTony Wickham protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 918f58e61d02fcb0ca90a2803e76a8792ec2c1f99aTony Wickham super.onMeasure(widthMeasureSpec, heightMeasureSpec); 928f58e61d02fcb0ca90a2803e76a8792ec2c1f99aTony Wickham mPillRect.set(0, 0, getMeasuredWidth(), getMeasuredHeight()); 938f58e61d02fcb0ca90a2803e76a8792ec2c1f99aTony Wickham } 948f58e61d02fcb0ca90a2803e76a8792ec2c1f99aTony Wickham 955836bf728e85c1c4fae67862deb4e973ac55e944Sunny Goyal /** package private **/ 965836bf728e85c1c4fae67862deb4e973ac55e944Sunny Goyal void applyShortcutInfo(UnbadgedShortcutInfo info, DeepShortcutsContainer container) { 975836bf728e85c1c4fae67862deb4e973ac55e944Sunny Goyal mInfo = info; 98a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal IconCache cache = LauncherAppState.getInstance().getIconCache(); 99a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal mBubbleText.applyFromShortcutInfo(info, cache); 100a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal mIconView.setBackground(mBubbleText.getIcon()); 1015836bf728e85c1c4fae67862deb4e973ac55e944Sunny Goyal 1025836bf728e85c1c4fae67862deb4e973ac55e944Sunny Goyal // Use the long label as long as it exists and fits. 1035836bf728e85c1c4fae67862deb4e973ac55e944Sunny Goyal CharSequence longLabel = info.mDetail.getLongLabel(); 1045836bf728e85c1c4fae67862deb4e973ac55e944Sunny Goyal int availableWidth = mBubbleText.getWidth() - mBubbleText.getTotalPaddingLeft() 1055836bf728e85c1c4fae67862deb4e973ac55e944Sunny Goyal - mBubbleText.getTotalPaddingRight(); 1065836bf728e85c1c4fae67862deb4e973ac55e944Sunny Goyal boolean usingLongLabel = !TextUtils.isEmpty(longLabel) 1075836bf728e85c1c4fae67862deb4e973ac55e944Sunny Goyal && mBubbleText.getPaint().measureText(longLabel.toString()) <= availableWidth; 1085836bf728e85c1c4fae67862deb4e973ac55e944Sunny Goyal mBubbleText.setText(usingLongLabel ? longLabel : info.mDetail.getShortLabel()); 1095836bf728e85c1c4fae67862deb4e973ac55e944Sunny Goyal 1105836bf728e85c1c4fae67862deb4e973ac55e944Sunny Goyal // TODO: Add the click handler to this view directly and not the child view. 1115836bf728e85c1c4fae67862deb4e973ac55e944Sunny Goyal mBubbleText.setOnClickListener(Launcher.getLauncher(getContext())); 1125836bf728e85c1c4fae67862deb4e973ac55e944Sunny Goyal mBubbleText.setOnLongClickListener(container); 1135836bf728e85c1c4fae67862deb4e973ac55e944Sunny Goyal mBubbleText.setOnTouchListener(container); 1145836bf728e85c1c4fae67862deb4e973ac55e944Sunny Goyal } 1155836bf728e85c1c4fae67862deb4e973ac55e944Sunny Goyal 1165836bf728e85c1c4fae67862deb4e973ac55e944Sunny Goyal /** 1175836bf728e85c1c4fae67862deb4e973ac55e944Sunny Goyal * Returns the shortcut info that is suitable to be added on the homescreen 1185836bf728e85c1c4fae67862deb4e973ac55e944Sunny Goyal */ 1195836bf728e85c1c4fae67862deb4e973ac55e944Sunny Goyal public ShortcutInfo getFinalInfo() { 1205836bf728e85c1c4fae67862deb4e973ac55e944Sunny Goyal ShortcutInfo badged = new ShortcutInfo(mInfo); 1215836bf728e85c1c4fae67862deb4e973ac55e944Sunny Goyal // Queue an update task on the worker thread. This ensures that the badged 1225836bf728e85c1c4fae67862deb4e973ac55e944Sunny Goyal // shortcut eventually gets its icon updated. 1235836bf728e85c1c4fae67862deb4e973ac55e944Sunny Goyal Launcher.getLauncher(getContext()).getModel().updateShortcutInfo(mInfo.mDetail, badged); 1245836bf728e85c1c4fae67862deb4e973ac55e944Sunny Goyal return badged; 1258f58e61d02fcb0ca90a2803e76a8792ec2c1f99aTony Wickham } 1268f58e61d02fcb0ca90a2803e76a8792ec2c1f99aTony Wickham 127a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal public View getIconView() { 128a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal return mIconView; 129a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal } 130a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal 131a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal /** 1320ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickham * Creates an animator to play when the shortcut container is being opened. 133a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal */ 1340ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickham public Animator createOpenAnimation(boolean isContainerAboveIcon, boolean pivotLeft) { 135a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal Point center = getIconCenter(); 1360ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickham ValueAnimator openAnimator = new ZoomRevealOutlineProvider(center.x, center.y, 1370ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickham mPillRect, this, mIconView, isContainerAboveIcon, pivotLeft) 1380ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickham .createRevealAnimator(this, false); 1390ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickham mOpenAnimationProgress = 0f; 1400ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickham openAnimator.addUpdateListener(this); 1410ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickham return openAnimator; 1420ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickham } 1430ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickham 1440ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickham @Override 1450ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickham public void onAnimationUpdate(ValueAnimator valueAnimator) { 1460ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickham mOpenAnimationProgress = valueAnimator.getAnimatedFraction(); 1470ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickham } 1480ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickham 1490ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickham public boolean isOpenOrOpening() { 1500ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickham return mOpenAnimationProgress > 0; 1510ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickham } 1520ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickham 1530ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickham /** 1540ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickham * Creates an animator to play when the shortcut container is being closed. 1550ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickham */ 1560ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickham public Animator createCloseAnimation(boolean isContainerAboveIcon, boolean pivotLeft, 1570ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickham long duration) { 1580ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickham Point center = getIconCenter(); 1590ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickham ValueAnimator closeAnimator = new ZoomRevealOutlineProvider(center.x, center.y, 1600ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickham mPillRect, this, mIconView, isContainerAboveIcon, pivotLeft) 1610ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickham .createRevealAnimator(this, true); 1620ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickham // Scale down the duration and interpolator according to the progress 1630ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickham // that the open animation was at when the close started. 1640ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickham closeAnimator.setDuration((long) (duration * mOpenAnimationProgress)); 1650ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickham closeAnimator.setInterpolator(new CloseInterpolator(mOpenAnimationProgress)); 1660ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickham return closeAnimator; 167a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal } 168a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal 169a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal /** 170a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal * Creates an animator which clips the container to form a circle around the icon. 171a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal */ 172a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal public Animator collapseToIcon() { 173a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal int halfHeight = getMeasuredHeight() / 2; 174a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal int iconCenterX = getIconCenter().x; 175a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal return new PillWidthRevealOutlineProvider(mPillRect, 176a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal iconCenterX - halfHeight, iconCenterX + halfHeight) 1770ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickham .createRevealAnimator(this, true); 1788f58e61d02fcb0ca90a2803e76a8792ec2c1f99aTony Wickham } 1798f58e61d02fcb0ca90a2803e76a8792ec2c1f99aTony Wickham 1808f58e61d02fcb0ca90a2803e76a8792ec2c1f99aTony Wickham /** 181a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal * Returns the position of the center of the icon relative to the container. 1828f58e61d02fcb0ca90a2803e76a8792ec2c1f99aTony Wickham */ 183a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal public Point getIconCenter() { 184a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal sTempPoint.y = sTempPoint.x = getMeasuredHeight() / 2; 185a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal if (Utilities.isRtl(getResources())) { 186a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal sTempPoint.x = getMeasuredWidth() - sTempPoint.x; 187a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal } 188a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal return sTempPoint; 189a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal } 190a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal 191a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal /** 192a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal * Extension of {@link PillRevealOutlineProvider} which scales the icon based on the height. 193a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal */ 194a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal private static class ZoomRevealOutlineProvider extends PillRevealOutlineProvider { 195a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal 196a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal private final View mTranslateView; 197a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal private final View mZoomView; 198a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal 199a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal private final float mFullHeight; 200a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal private final float mTranslateYMultiplier; 201a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal 202a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal private final boolean mPivotLeft; 203a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal private final float mTranslateX; 204a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal 205a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal public ZoomRevealOutlineProvider(int x, int y, Rect pillRect, 206a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal View translateView, View zoomView, boolean isContainerAboveIcon, boolean pivotLeft) { 207a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal super(x, y, pillRect); 208a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal mTranslateView = translateView; 209a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal mZoomView = zoomView; 210a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal mFullHeight = pillRect.height(); 211a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal 212a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal mTranslateYMultiplier = isContainerAboveIcon ? 0.5f : -0.5f; 213a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal 214a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal mPivotLeft = pivotLeft; 215a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal mTranslateX = pivotLeft ? pillRect.height() / 2 : pillRect.right - pillRect.height() / 2; 216a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal } 217a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal 218a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal @Override 219a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal public void setProgress(float progress) { 220a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal super.setProgress(progress); 221a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal 222a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal mZoomView.setScaleX(progress); 223a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal mZoomView.setScaleY(progress); 224a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal 225a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal float height = mOutline.height(); 226a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal mTranslateView.setTranslationY(mTranslateYMultiplier * (mFullHeight - height)); 227a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal 228a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal float pivotX = mPivotLeft ? (mOutline.left + height / 2) : (mOutline.right - height / 2); 229a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal mTranslateView.setTranslationX(mTranslateX - pivotX); 230a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal } 2311bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham } 2320ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickham 2330ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickham /** 2340ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickham * An interpolator that reverses the current open animation progress. 2350ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickham */ 2360ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickham private static class CloseInterpolator extends LogAccelerateInterpolator { 2370ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickham private float mStartProgress; 2380ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickham private float mRemainingProgress; 2390ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickham 2400ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickham /** 2410ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickham * @param openAnimationProgress The progress that the open interpolator ended at. 2420ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickham */ 2430ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickham public CloseInterpolator(float openAnimationProgress) { 2440ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickham super(100, 0); 2450ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickham mStartProgress = 1f - openAnimationProgress; 2460ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickham mRemainingProgress = openAnimationProgress; 2470ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickham } 2480ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickham 2490ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickham @Override 2500ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickham public float getInterpolation(float v) { 2510ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickham return mStartProgress + super.getInterpolation(v) * mRemainingProgress; 2520ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickham } 2530ba81607e30c008a7aa24ca76d74f9c4aaafd053Tony Wickham } 2541bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham} 255