Updating the PreloadIconDrawable
> The drawable gets the path from MaskIconDrawable path, instead of using a circle > The progress changes are animated as well Bug: 34831873 Change-Id: I4e7f0b610f4fd94de8e0cfcf8b179b775cf0b4d8
Before Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 847 B |
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
<maskable-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:color="#FFE0E0E0"/>
|
||||
<foreground>
|
||||
<com.android.launcher3.graphics.FixedScaleDrawable />
|
||||
</foreground>
|
||||
</maskable-icon>
|
Before Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 6.6 KiB |
Before Width: | Height: | Size: 2.9 KiB |
|
@ -72,12 +72,6 @@
|
|||
<attr name="folderItems" format="reference" />
|
||||
</declare-styleable>
|
||||
|
||||
<declare-styleable name="PreloadIconDrawable">
|
||||
<attr name="background" format="reference" />
|
||||
<attr name="ringOutset" format="dimension" />
|
||||
<attr name="indicatorSize" format="dimension" />
|
||||
</declare-styleable>
|
||||
|
||||
<declare-styleable name="InsettableFrameLayout_Layout">
|
||||
<attr name="layout_ignoreInsets" format="boolean" />
|
||||
</declare-styleable>
|
||||
|
|
|
@ -52,5 +52,4 @@
|
|||
<color name="fallback_secondary_color">#FF37474F</color>
|
||||
|
||||
<color name="notification_icon_default_color">#757575</color> <!-- Gray 600 -->
|
||||
<color name="legacy_icon_background">#FFE0E0E0</color>
|
||||
</resources>
|
||||
|
|
|
@ -148,17 +148,4 @@
|
|||
</style>
|
||||
|
||||
<style name="DropTargetButton" parent="DropTargetButtonBase" />
|
||||
|
||||
<!-- Virtual preloaders -->
|
||||
<style name="PreloadIcon">
|
||||
<item name="background">@drawable/virtual_preload</item>
|
||||
<item name="indicatorSize">4dp</item>
|
||||
<item name="ringOutset">4dp</item>
|
||||
</style>
|
||||
|
||||
<style name="PreloadIcon.Folder">
|
||||
<item name="background">@drawable/virtual_preload_folder</item>
|
||||
<item name="indicatorSize">4dp</item>
|
||||
<item name="ringOutset">4dp</item>
|
||||
</style>
|
||||
</resources>
|
||||
|
|
|
@ -19,7 +19,6 @@ package com.android.launcher3;
|
|||
import android.content.Context;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.Resources.Theme;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
|
@ -27,7 +26,6 @@ import android.graphics.Paint;
|
|||
import android.graphics.Region;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.SparseArray;
|
||||
import android.util.TypedValue;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
|
@ -45,6 +43,7 @@ import com.android.launcher3.folder.FolderIcon;
|
|||
import com.android.launcher3.graphics.DrawableFactory;
|
||||
import com.android.launcher3.graphics.HolographicOutlineHelper;
|
||||
import com.android.launcher3.graphics.IconPalette;
|
||||
import com.android.launcher3.graphics.PreloadIconDrawable;
|
||||
import com.android.launcher3.model.PackageItemInfo;
|
||||
|
||||
import java.text.NumberFormat;
|
||||
|
@ -57,8 +56,6 @@ import java.text.NumberFormat;
|
|||
public class BubbleTextView extends TextView
|
||||
implements BaseRecyclerViewFastScrollBar.FastScrollFocusableView, ItemInfoUpdateReceiver {
|
||||
|
||||
private static SparseArray<Theme> sPreloaderThemes = new SparseArray<Theme>(2);
|
||||
|
||||
// Dimensions in DP
|
||||
private static final float AMBIENT_SHADOW_RADIUS = 2.5f;
|
||||
private static final float KEY_SHADOW_RADIUS = 1f;
|
||||
|
@ -423,10 +420,6 @@ public class BubbleTextView extends TextView
|
|||
super.onAttachedToWindow();
|
||||
|
||||
if (mBackground != null) mBackground.setCallback(this);
|
||||
|
||||
if (mIcon instanceof PreloadIconDrawable) {
|
||||
((PreloadIconDrawable) mIcon).applyPreloaderTheme(getPreloaderTheme());
|
||||
}
|
||||
mSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
|
||||
}
|
||||
|
||||
|
@ -495,7 +488,8 @@ public class BubbleTextView extends TextView
|
|||
if (mIcon instanceof PreloadIconDrawable) {
|
||||
preloadDrawable = (PreloadIconDrawable) mIcon;
|
||||
} else {
|
||||
preloadDrawable = new PreloadIconDrawable(mIcon, getPreloaderTheme());
|
||||
preloadDrawable = DrawableFactory.get(getContext())
|
||||
.newPendingIcon(info.iconBitmap, getContext());
|
||||
setIcon(preloadDrawable);
|
||||
}
|
||||
|
||||
|
@ -520,20 +514,6 @@ public class BubbleTextView extends TextView
|
|||
: null;
|
||||
}
|
||||
|
||||
private Theme getPreloaderTheme() {
|
||||
Object tag = getTag();
|
||||
int style = ((tag != null) && (tag instanceof ShortcutInfo) &&
|
||||
(((ShortcutInfo) tag).container >= 0)) ? R.style.PreloadIcon_Folder
|
||||
: R.style.PreloadIcon;
|
||||
Theme theme = sPreloaderThemes.get(style);
|
||||
if (theme == null) {
|
||||
theme = getResources().newTheme();
|
||||
theme.applyStyle(style, true);
|
||||
sPreloaderThemes.put(style, theme);
|
||||
}
|
||||
return theme;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the icon for this view based on the layout direction.
|
||||
*/
|
||||
|
|
|
@ -120,7 +120,7 @@ public class FastBitmapDrawable extends Drawable {
|
|||
|
||||
public FastBitmapDrawable(Bitmap b) {
|
||||
mBitmap = b;
|
||||
setBounds(0, 0, b.getWidth(), b.getHeight());
|
||||
setFilterBitmap(true);
|
||||
}
|
||||
|
||||
public void applyIconBadge(BadgeInfo badgeInfo, BadgeRenderer badgeRenderer) {
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
package com.android.launcher3;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources.Theme;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
|
@ -33,8 +32,8 @@ import android.view.ContextThemeWrapper;
|
|||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
|
||||
import com.android.launcher3.graphics.DrawableFactory;
|
||||
import com.android.launcher3.IconCache.ItemInfoUpdateReceiver;
|
||||
import com.android.launcher3.graphics.DrawableFactory;
|
||||
import com.android.launcher3.model.PackageItemInfo;
|
||||
|
||||
public class PendingAppWidgetHostView extends LauncherAppWidgetHostView
|
||||
|
@ -42,8 +41,6 @@ public class PendingAppWidgetHostView extends LauncherAppWidgetHostView
|
|||
private static final float SETUP_ICON_SIZE_FACTOR = 2f / 5;
|
||||
private static final float MIN_SATUNATION = 0.7f;
|
||||
|
||||
private static Theme sPreloaderTheme;
|
||||
|
||||
private final Rect mRect = new Rect();
|
||||
private View mDefaultView;
|
||||
private OnClickListener mClickListener;
|
||||
|
@ -149,13 +146,8 @@ public class PendingAppWidgetHostView extends LauncherAppWidgetHostView
|
|||
|
||||
updateSettingColor();
|
||||
} else {
|
||||
if (sPreloaderTheme == null) {
|
||||
sPreloaderTheme = getResources().newTheme();
|
||||
sPreloaderTheme.applyStyle(R.style.PreloadIcon, true);
|
||||
}
|
||||
|
||||
FastBitmapDrawable drawable = drawableFactory.newIcon(mIcon, mInfo);
|
||||
mCenterDrawable = new PreloadIconDrawable(drawable, sPreloaderTheme);
|
||||
mCenterDrawable = DrawableFactory.get(getContext())
|
||||
.newPendingIcon(mIcon, getContext());
|
||||
mCenterDrawable.setCallback(this);
|
||||
mSettingIconDrawable = null;
|
||||
applyState();
|
||||
|
@ -226,13 +218,10 @@ public class PendingAppWidgetHostView extends LauncherAppWidgetHostView
|
|||
int availableHeight = getHeight() - paddingTop - paddingBottom - 2 * minPadding;
|
||||
|
||||
if (mSettingIconDrawable == null) {
|
||||
int outset = (mCenterDrawable instanceof PreloadIconDrawable) ?
|
||||
((PreloadIconDrawable) mCenterDrawable).getOutset() : 0;
|
||||
int maxSize = grid.iconSizePx + 2 * outset;
|
||||
int maxSize = grid.iconSizePx;
|
||||
int size = Math.min(maxSize, Math.min(availableWidth, availableHeight));
|
||||
|
||||
mRect.set(0, 0, size, size);
|
||||
mRect.inset(outset, outset);
|
||||
mRect.offsetTo((getWidth() - mRect.width()) / 2, (getHeight() - mRect.height()) / 2);
|
||||
mCenterDrawable.setBounds(mRect);
|
||||
} else {
|
||||
|
|
|
@ -1,252 +0,0 @@
|
|||
package com.android.launcher3;
|
||||
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.content.res.Resources.Theme;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.ColorFilter;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
||||
public class PreloadIconDrawable extends Drawable {
|
||||
|
||||
private static final float ANIMATION_PROGRESS_STOPPED = -1.0f;
|
||||
private static final float ANIMATION_PROGRESS_STARTED = 0f;
|
||||
private static final float ANIMATION_PROGRESS_COMPLETED = 1.0f;
|
||||
|
||||
private static final float MIN_SATURATION = 0.2f;
|
||||
private static final float MIN_LIGHTNESS = 0.6f;
|
||||
|
||||
private static final float ICON_SCALE_FACTOR = 0.5f;
|
||||
private static final int DEFAULT_COLOR = 0xFF009688;
|
||||
|
||||
private static final Rect sTempRect = new Rect();
|
||||
|
||||
private final RectF mIndicatorRect = new RectF();
|
||||
private boolean mIndicatorRectDirty;
|
||||
|
||||
private final Paint mPaint;
|
||||
public final Drawable mIcon;
|
||||
|
||||
private Drawable mBgDrawable;
|
||||
private int mRingOutset;
|
||||
|
||||
private int mIndicatorColor = 0;
|
||||
|
||||
/**
|
||||
* Indicates the progress of the preloader [0-100]. If it goes above 100, only the icon
|
||||
* is shown with no progress bar.
|
||||
*/
|
||||
private int mProgress = 0;
|
||||
|
||||
private float mAnimationProgress = ANIMATION_PROGRESS_STOPPED;
|
||||
private ObjectAnimator mAnimator;
|
||||
|
||||
public PreloadIconDrawable(Drawable icon, Theme theme) {
|
||||
mIcon = icon;
|
||||
|
||||
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
mPaint.setStyle(Paint.Style.STROKE);
|
||||
mPaint.setStrokeCap(Paint.Cap.ROUND);
|
||||
|
||||
setBounds(icon.getBounds());
|
||||
applyPreloaderTheme(theme);
|
||||
onLevelChange(0);
|
||||
}
|
||||
|
||||
public void applyPreloaderTheme(Theme t) {
|
||||
TypedArray ta = t.obtainStyledAttributes(R.styleable.PreloadIconDrawable);
|
||||
mBgDrawable = ta.getDrawable(R.styleable.PreloadIconDrawable_background);
|
||||
mBgDrawable.setFilterBitmap(true);
|
||||
mPaint.setStrokeWidth(ta.getDimension(R.styleable.PreloadIconDrawable_indicatorSize, 0));
|
||||
mRingOutset = ta.getDimensionPixelSize(R.styleable.PreloadIconDrawable_ringOutset, 0);
|
||||
ta.recycle();
|
||||
onBoundsChange(getBounds());
|
||||
invalidateSelf();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBoundsChange(Rect bounds) {
|
||||
mIcon.setBounds(bounds);
|
||||
if (mBgDrawable != null) {
|
||||
sTempRect.set(bounds);
|
||||
sTempRect.inset(-mRingOutset, -mRingOutset);
|
||||
mBgDrawable.setBounds(sTempRect);
|
||||
}
|
||||
mIndicatorRectDirty = true;
|
||||
}
|
||||
|
||||
public int getOutset() {
|
||||
return mRingOutset;
|
||||
}
|
||||
|
||||
/**
|
||||
* The size of the indicator is same as the content region of the {@link #mBgDrawable} minus
|
||||
* half the stroke size to accommodate the indicator.
|
||||
*/
|
||||
private void initIndicatorRect() {
|
||||
Drawable d = mBgDrawable;
|
||||
Rect bounds = d.getBounds();
|
||||
|
||||
d.getPadding(sTempRect);
|
||||
// Amount by which padding has to be scaled
|
||||
float paddingScaleX = ((float) bounds.width()) / d.getIntrinsicWidth();
|
||||
float paddingScaleY = ((float) bounds.height()) / d.getIntrinsicHeight();
|
||||
mIndicatorRect.set(
|
||||
bounds.left + sTempRect.left * paddingScaleX,
|
||||
bounds.top + sTempRect.top * paddingScaleY,
|
||||
bounds.right - sTempRect.right * paddingScaleX,
|
||||
bounds.bottom - sTempRect.bottom * paddingScaleY);
|
||||
|
||||
float inset = mPaint.getStrokeWidth() / 2;
|
||||
mIndicatorRect.inset(inset, inset);
|
||||
mIndicatorRectDirty = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas) {
|
||||
final Rect r = new Rect(getBounds());
|
||||
if (canvas.getClipBounds(sTempRect) && !Rect.intersects(sTempRect, r)) {
|
||||
// The draw region has been clipped.
|
||||
return;
|
||||
}
|
||||
if (mIndicatorRectDirty) {
|
||||
initIndicatorRect();
|
||||
}
|
||||
final float iconScale;
|
||||
|
||||
if ((mAnimationProgress >= ANIMATION_PROGRESS_STARTED)
|
||||
&& (mAnimationProgress < ANIMATION_PROGRESS_COMPLETED)) {
|
||||
mPaint.setAlpha((int) ((1 - mAnimationProgress) * 255));
|
||||
mBgDrawable.setAlpha(mPaint.getAlpha());
|
||||
mBgDrawable.draw(canvas);
|
||||
canvas.drawOval(mIndicatorRect, mPaint);
|
||||
|
||||
iconScale = ICON_SCALE_FACTOR + (1 - ICON_SCALE_FACTOR) * mAnimationProgress;
|
||||
} else if (mAnimationProgress == ANIMATION_PROGRESS_STOPPED) {
|
||||
mPaint.setAlpha(255);
|
||||
iconScale = ICON_SCALE_FACTOR;
|
||||
mBgDrawable.setAlpha(255);
|
||||
mBgDrawable.draw(canvas);
|
||||
|
||||
if (mProgress >= 100) {
|
||||
canvas.drawOval(mIndicatorRect, mPaint);
|
||||
} else if (mProgress > 0) {
|
||||
canvas.drawArc(mIndicatorRect, -90, mProgress * 3.6f, false, mPaint);
|
||||
}
|
||||
} else {
|
||||
iconScale = 1;
|
||||
}
|
||||
|
||||
canvas.save();
|
||||
canvas.scale(iconScale, iconScale, r.exactCenterX(), r.exactCenterY());
|
||||
mIcon.draw(canvas);
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOpacity() {
|
||||
return PixelFormat.TRANSLUCENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAlpha(int alpha) {
|
||||
mIcon.setAlpha(alpha);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setColorFilter(ColorFilter cf) {
|
||||
mIcon.setColorFilter(cf);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean onLevelChange(int level) {
|
||||
mProgress = level;
|
||||
|
||||
// Stop Animation
|
||||
if (mAnimator != null) {
|
||||
mAnimator.cancel();
|
||||
mAnimator = null;
|
||||
}
|
||||
mAnimationProgress = ANIMATION_PROGRESS_STOPPED;
|
||||
if (level > 0) {
|
||||
// Set the paint color only when the level changes, so that the dominant color
|
||||
// is only calculated when needed.
|
||||
mPaint.setColor(getIndicatorColor());
|
||||
}
|
||||
if (mIcon instanceof FastBitmapDrawable) {
|
||||
((FastBitmapDrawable) mIcon).setIsDisabled(level < 100);
|
||||
}
|
||||
|
||||
invalidateSelf();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the finish animation if it is has not been run after last level change.
|
||||
*/
|
||||
public void maybePerformFinishedAnimation() {
|
||||
if (mAnimationProgress > ANIMATION_PROGRESS_STOPPED) {
|
||||
return;
|
||||
}
|
||||
if (mAnimator != null) {
|
||||
mAnimator.cancel();
|
||||
}
|
||||
setAnimationProgress(ANIMATION_PROGRESS_STARTED);
|
||||
mAnimator = ObjectAnimator.ofFloat(this, "animationProgress",
|
||||
ANIMATION_PROGRESS_STARTED, ANIMATION_PROGRESS_COMPLETED);
|
||||
mAnimator.start();
|
||||
}
|
||||
|
||||
public void setAnimationProgress(float progress) {
|
||||
if (progress != mAnimationProgress) {
|
||||
mAnimationProgress = progress;
|
||||
invalidateSelf();
|
||||
}
|
||||
}
|
||||
|
||||
public float getAnimationProgress() {
|
||||
return mAnimationProgress;
|
||||
}
|
||||
|
||||
public boolean hasNotCompleted() {
|
||||
return mAnimationProgress < ANIMATION_PROGRESS_COMPLETED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIntrinsicHeight() {
|
||||
return mIcon.getIntrinsicHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIntrinsicWidth() {
|
||||
return mIcon.getIntrinsicWidth();
|
||||
}
|
||||
|
||||
private int getIndicatorColor() {
|
||||
if (mIndicatorColor != 0) {
|
||||
return mIndicatorColor;
|
||||
}
|
||||
if (!(mIcon instanceof FastBitmapDrawable)) {
|
||||
mIndicatorColor = DEFAULT_COLOR;
|
||||
return mIndicatorColor;
|
||||
}
|
||||
mIndicatorColor = Utilities.findDominantColorByHue(
|
||||
((FastBitmapDrawable) mIcon).getBitmap(), 20);
|
||||
|
||||
// Make sure that the dominant color has enough saturation to be visible properly.
|
||||
float[] hsv = new float[3];
|
||||
Color.colorToHSV(mIndicatorColor, hsv);
|
||||
if (hsv[1] < MIN_SATURATION) {
|
||||
mIndicatorColor = DEFAULT_COLOR;
|
||||
return mIndicatorColor;
|
||||
}
|
||||
hsv[2] = Math.max(MIN_LIGHTNESS, hsv[2]);
|
||||
mIndicatorColor = Color.HSVToColor(hsv);
|
||||
return mIndicatorColor;
|
||||
}
|
||||
}
|
|
@ -72,6 +72,7 @@ import com.android.launcher3.dragndrop.SpringLoadedDragController;
|
|||
import com.android.launcher3.folder.Folder;
|
||||
import com.android.launcher3.folder.FolderIcon;
|
||||
import com.android.launcher3.graphics.DragPreviewProvider;
|
||||
import com.android.launcher3.graphics.PreloadIconDrawable;
|
||||
import com.android.launcher3.popup.PopupContainerWithArrow;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
|
||||
|
|
|
@ -53,13 +53,11 @@ import com.android.launcher3.DropTarget.DragObject;
|
|||
import com.android.launcher3.FastBitmapDrawable;
|
||||
import com.android.launcher3.FolderInfo;
|
||||
import com.android.launcher3.FolderInfo.FolderListener;
|
||||
import com.android.launcher3.IconCache;
|
||||
import com.android.launcher3.ItemInfo;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherAnimUtils;
|
||||
import com.android.launcher3.LauncherSettings;
|
||||
import com.android.launcher3.OnAlarmListener;
|
||||
import com.android.launcher3.PreloadIconDrawable;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.ShortcutInfo;
|
||||
import com.android.launcher3.SimpleOnStylusPressListener;
|
||||
|
@ -245,7 +243,7 @@ public class FolderIcon extends FrameLayout implements FolderListener {
|
|||
};
|
||||
|
||||
public Drawable prepareCreate(final View destView) {
|
||||
Drawable animateDrawable = getTopDrawable((TextView) destView);
|
||||
Drawable animateDrawable = ((TextView) destView).getCompoundDrawables()[1];
|
||||
computePreviewDrawingParams(animateDrawable.getIntrinsicWidth(),
|
||||
destView.getMeasuredWidth());
|
||||
return animateDrawable;
|
||||
|
@ -270,7 +268,7 @@ public class FolderIcon extends FrameLayout implements FolderListener {
|
|||
}
|
||||
|
||||
public void performDestroyAnimation(final View finalView, Runnable onCompleteRunnable) {
|
||||
Drawable animateDrawable = getTopDrawable((TextView) finalView);
|
||||
Drawable animateDrawable = ((TextView) finalView).getCompoundDrawables()[1];
|
||||
computePreviewDrawingParams(animateDrawable.getIntrinsicWidth(),
|
||||
finalView.getMeasuredWidth());
|
||||
|
||||
|
@ -771,11 +769,6 @@ public class FolderIcon extends FrameLayout implements FolderListener {
|
|||
}
|
||||
}
|
||||
|
||||
private Drawable getTopDrawable(TextView v) {
|
||||
Drawable d = v.getCompoundDrawables()[1];
|
||||
return (d instanceof PreloadIconDrawable) ? ((PreloadIconDrawable) d).mIcon : d;
|
||||
}
|
||||
|
||||
class FolderPreviewItemAnim {
|
||||
ValueAnimator mValueAnimator;
|
||||
float finalScale;
|
||||
|
@ -892,7 +885,7 @@ public class FolderIcon extends FrameLayout implements FolderListener {
|
|||
|
||||
for (int i = 0; i < mDrawingParams.size(); i++) {
|
||||
PreviewItemDrawingParams p = mDrawingParams.get(i);
|
||||
p.drawable = getTopDrawable((TextView) items.get(i));
|
||||
p.drawable = ((TextView) items.get(i)).getCompoundDrawables()[1];
|
||||
|
||||
if (!animate || FeatureFlags.LAUNCHER3_LEGACY_FOLDER_ICON) {
|
||||
computePreviewItemDrawingParams(i, nItemsInPreview, p);
|
||||
|
|
|
@ -27,7 +27,6 @@ import android.widget.TextView;
|
|||
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherAppWidgetHostView;
|
||||
import com.android.launcher3.PreloadIconDrawable;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Workspace;
|
||||
import com.android.launcher3.config.ProviderConfig;
|
||||
|
@ -185,10 +184,6 @@ public class DragPreviewProvider {
|
|||
} else {
|
||||
bounds.offsetTo(0, 0);
|
||||
}
|
||||
if (d instanceof PreloadIconDrawable) {
|
||||
int inset = -((PreloadIconDrawable) d).getOutset();
|
||||
bounds.inset(inset, inset);
|
||||
}
|
||||
return bounds;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,12 +21,14 @@ import android.content.res.Resources;
|
|||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Process;
|
||||
import android.os.UserHandle;
|
||||
import android.support.annotation.UiThread;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.launcher3.FastBitmapDrawable;
|
||||
import com.android.launcher3.ItemInfo;
|
||||
|
@ -41,9 +43,13 @@ import java.util.HashMap;
|
|||
*/
|
||||
public class DrawableFactory {
|
||||
|
||||
private static final String TAG = "DrawableFactory";
|
||||
|
||||
private static DrawableFactory sInstance;
|
||||
private static final Object LOCK = new Object();
|
||||
|
||||
private Path mPreloadProgressPath;
|
||||
|
||||
public static DrawableFactory get(Context context) {
|
||||
synchronized (LOCK) {
|
||||
if (sInstance == null) {
|
||||
|
@ -61,9 +67,38 @@ public class DrawableFactory {
|
|||
* Returns a FastBitmapDrawable with the icon.
|
||||
*/
|
||||
public FastBitmapDrawable newIcon(Bitmap icon, ItemInfo info) {
|
||||
FastBitmapDrawable d = new FastBitmapDrawable(icon);
|
||||
d.setFilterBitmap(true);
|
||||
return d;
|
||||
return new FastBitmapDrawable(icon);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a FastBitmapDrawable with the icon.
|
||||
*/
|
||||
public PreloadIconDrawable newPendingIcon(Bitmap icon, Context context) {
|
||||
if (mPreloadProgressPath == null) {
|
||||
mPreloadProgressPath = getPreloadProgressPath(context);
|
||||
}
|
||||
return new PreloadIconDrawable(icon, mPreloadProgressPath);
|
||||
}
|
||||
|
||||
|
||||
protected Path getPreloadProgressPath(Context context) {
|
||||
if (Utilities.isAtLeastO()) {
|
||||
try {
|
||||
// Try to load the path from Mask Icon
|
||||
Drawable maskIcon = context.getDrawable(R.drawable.mask_drawable_wrapper);
|
||||
maskIcon.setBounds(0, 0,
|
||||
PreloadIconDrawable.PATH_SIZE, PreloadIconDrawable.PATH_SIZE);
|
||||
return (Path) maskIcon.getClass().getMethod("getIconMask").invoke(maskIcon);
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Error loading mask icon", e);
|
||||
}
|
||||
}
|
||||
|
||||
// Create a circle static from top center and going clockwise.
|
||||
Path p = new Path();
|
||||
p.moveTo(PreloadIconDrawable.PATH_SIZE / 2, 0);
|
||||
p.addArc(0, 0, PreloadIconDrawable.PATH_SIZE, PreloadIconDrawable.PATH_SIZE, -90, 360);
|
||||
return p;
|
||||
}
|
||||
|
||||
public AllAppsBackgroundDrawable getAllAppsBackground(Context context) {
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
package com.android.launcher3.graphics;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.Resources.Theme;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.DrawableWrapper;
|
||||
import android.os.Build;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
/**
|
||||
* Extension of {@link DrawableWrapper} which scales the child drawables by a fixed amount.
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.N)
|
||||
public class FixedScaleDrawable extends DrawableWrapper {
|
||||
|
||||
// TODO b/33553066 use the constant defined in MaskableIconDrawable
|
||||
private static final float LEGACY_ICON_SCALE = .7f * .6667f;
|
||||
|
||||
public FixedScaleDrawable() {
|
||||
super(new ColorDrawable());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas) {
|
||||
int saveCount = canvas.save(Canvas.MATRIX_SAVE_FLAG);
|
||||
canvas.scale(LEGACY_ICON_SCALE, LEGACY_ICON_SCALE,
|
||||
getBounds().exactCenterX(), getBounds().exactCenterY());
|
||||
super.draw(canvas);
|
||||
canvas.restoreToCount(saveCount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs) { }
|
||||
|
||||
@Override
|
||||
public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme) { }
|
||||
}
|
|
@ -32,16 +32,42 @@ public class IconPalette {
|
|||
private static final boolean DEBUG = false;
|
||||
private static final String TAG = "IconPalette";
|
||||
|
||||
public int backgroundColor;
|
||||
public int textColor;
|
||||
public int secondaryColor;
|
||||
private static final float MIN_PRELOAD_COLOR_SATURATION = 0.2f;
|
||||
private static final float MIN_PRELOAD_COLOR_LIGHTNESS = 0.6f;
|
||||
private static final int DEFAULT_PRELOAD_COLOR = 0xFF009688;
|
||||
|
||||
public final int dominantColor;
|
||||
public final int backgroundColor;
|
||||
public final int textColor;
|
||||
public final int secondaryColor;
|
||||
|
||||
private IconPalette(int color) {
|
||||
dominantColor = color;
|
||||
backgroundColor = getMutedColor(dominantColor);
|
||||
textColor = getTextColorForBackground(backgroundColor);
|
||||
secondaryColor = getLowContrastColor(backgroundColor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a color suitable for the progress bar color of preload icon.
|
||||
*/
|
||||
public int getPreloadProgressColor() {
|
||||
int result = dominantColor;
|
||||
|
||||
// Make sure that the dominant color has enough saturation to be visible properly.
|
||||
float[] hsv = new float[3];
|
||||
Color.colorToHSV(result, hsv);
|
||||
if (hsv[1] < MIN_PRELOAD_COLOR_SATURATION) {
|
||||
result = DEFAULT_PRELOAD_COLOR;
|
||||
} else {
|
||||
hsv[2] = Math.max(MIN_PRELOAD_COLOR_LIGHTNESS, hsv[2]);
|
||||
result = Color.HSVToColor(hsv);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static IconPalette fromDominantColor(int dominantColor) {
|
||||
IconPalette palette = new IconPalette();
|
||||
palette.backgroundColor = getMutedColor(dominantColor);
|
||||
palette.textColor = getTextColorForBackground(palette.backgroundColor);
|
||||
palette.secondaryColor = getLowContrastColor(palette.backgroundColor);
|
||||
return palette;
|
||||
return new IconPalette(dominantColor);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -29,13 +29,10 @@ import android.graphics.PaintFlagsDrawFilter;
|
|||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.PaintDrawable;
|
||||
import android.graphics.drawable.ScaleDrawable;
|
||||
import android.os.Process;
|
||||
import android.os.UserHandle;
|
||||
import android.view.Gravity;
|
||||
|
||||
import com.android.launcher3.AppInfo;
|
||||
import com.android.launcher3.IconCache;
|
||||
|
@ -52,8 +49,6 @@ import com.android.launcher3.shortcuts.ShortcutInfoCompat;
|
|||
* Helper methods for generating various launcher icons
|
||||
*/
|
||||
public class LauncherIcons {
|
||||
// TODO b/33553066 use the constant defined in MaskableIconDrawable
|
||||
private static final float LEGACY_ICON_SCALE = .7f * .6667f;
|
||||
|
||||
private static final Rect sOldBounds = new Rect();
|
||||
private static final Canvas sCanvas = new Canvas();
|
||||
|
@ -236,17 +231,16 @@ public class LauncherIcons {
|
|||
if (!(ProviderConfig.IS_DOGFOOD_BUILD && Utilities.isAtLeastO())) {
|
||||
return drawable;
|
||||
}
|
||||
int color = context.getResources().getColor(R.color.legacy_icon_background);
|
||||
ColorDrawable colorDrawable = new ColorDrawable(color);
|
||||
ScaleDrawable scaleDrawable = new ScaleDrawable(drawable,
|
||||
Gravity.CENTER, LEGACY_ICON_SCALE, LEGACY_ICON_SCALE);
|
||||
scaleDrawable.setLevel(1);
|
||||
|
||||
try {
|
||||
Class clazz = Class.forName("android.graphics.drawable.MaskableIconDrawable");
|
||||
if (!clazz.isAssignableFrom(drawable.getClass())){
|
||||
if (!clazz.isAssignableFrom(drawable.getClass())) {
|
||||
Drawable maskWrapper =
|
||||
context.getDrawable(R.drawable.mask_drawable_wrapper).mutate();
|
||||
((FixedScaleDrawable) clazz.getMethod("getForeground").invoke(maskWrapper))
|
||||
.setDrawable(drawable);
|
||||
|
||||
return (Drawable) clazz.getConstructor(Drawable.class, Drawable.class)
|
||||
.newInstance(colorDrawable, scaleDrawable);
|
||||
return maskWrapper;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return drawable;
|
||||
|
|
|
@ -0,0 +1,289 @@
|
|||
/*
|
||||
* 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.graphics;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.PathMeasure;
|
||||
import android.graphics.Rect;
|
||||
import android.util.Property;
|
||||
import android.util.SparseArray;
|
||||
import android.view.animation.LinearInterpolator;
|
||||
|
||||
import com.android.launcher3.FastBitmapDrawable;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
/**
|
||||
* Extension of {@link FastBitmapDrawable} which shows a progress bar around the icon.
|
||||
*/
|
||||
public class PreloadIconDrawable extends FastBitmapDrawable {
|
||||
|
||||
private static final Property<PreloadIconDrawable, Float> INTERNAL_STATE =
|
||||
new Property<PreloadIconDrawable, Float>(Float.TYPE, "internalStateProgress") {
|
||||
@Override
|
||||
public Float get(PreloadIconDrawable object) {
|
||||
return object.mInternalStateProgress;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(PreloadIconDrawable object, Float value) {
|
||||
object.setInternalProgress(value);
|
||||
}
|
||||
};
|
||||
|
||||
public static final int PATH_SIZE = 100;
|
||||
|
||||
private static final float PROGRESS_WIDTH = 7;
|
||||
private static final float PROGRESS_GAP = 2;
|
||||
private static final int MAX_PAINT_ALPHA = 255;
|
||||
|
||||
private static final long DURATION_SCALE = 500;
|
||||
|
||||
// The smaller the number, the faster the animation would be.
|
||||
// Duration = COMPLETE_ANIM_FRACTION * DURATION_SCALE
|
||||
private static final float COMPLETE_ANIM_FRACTION = 0.3f;
|
||||
|
||||
private static final int COLOR_TRACK = 0x77EEEEEE;
|
||||
private static final int COLOR_SHADOW = 0x55000000;
|
||||
|
||||
private static final float SMALL_SCALE = 0.75f;
|
||||
|
||||
private static final SparseArray<WeakReference<Bitmap>> sShadowCache = new SparseArray<>();
|
||||
|
||||
private final Matrix mTmpMatrix = new Matrix();
|
||||
private final PathMeasure mPathMeasure = new PathMeasure();
|
||||
|
||||
// Path in [0, 100] bounds.
|
||||
private final Path mProgressPath;
|
||||
|
||||
private final Path mScaledTrackPath;
|
||||
private final Path mScaledProgressPath;
|
||||
private final Paint mProgressPaint;
|
||||
|
||||
private Bitmap mShadowBitmap;
|
||||
private int mIndicatorColor = 0;
|
||||
|
||||
private int mTrackAlpha;
|
||||
private float mTrackLength;
|
||||
private float mIconScale;
|
||||
|
||||
private boolean mRanFinishAnimation;
|
||||
|
||||
// Progress of the internal state. [0, 1] indicates the fraction of completed progress,
|
||||
// [1, (1 + COMPLETE_ANIM_FRACTION)] indicates the progress of zoom animation.
|
||||
private float mInternalStateProgress;
|
||||
|
||||
private ObjectAnimator mCurrentAnim;
|
||||
|
||||
/**
|
||||
* @param progressPath fixed path in the bounds [0, 0, 100, 100] representing a progress bar.
|
||||
*/
|
||||
public PreloadIconDrawable(Bitmap b, Path progressPath) {
|
||||
super(b);
|
||||
mProgressPath = progressPath;
|
||||
mScaledTrackPath = new Path();
|
||||
mScaledProgressPath = new Path();
|
||||
|
||||
mProgressPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
|
||||
mProgressPaint.setStyle(Paint.Style.STROKE);
|
||||
mProgressPaint.setStrokeCap(Paint.Cap.ROUND);
|
||||
|
||||
setInternalProgress(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBoundsChange(Rect bounds) {
|
||||
super.onBoundsChange(bounds);
|
||||
mTmpMatrix.setScale(
|
||||
(bounds.width() - PROGRESS_WIDTH - 2 * PROGRESS_GAP) / PATH_SIZE,
|
||||
(bounds.height() - PROGRESS_WIDTH - 2 * PROGRESS_GAP) / PATH_SIZE);
|
||||
mTmpMatrix.postTranslate(
|
||||
bounds.left + PROGRESS_WIDTH / 2 + PROGRESS_GAP,
|
||||
bounds.top + PROGRESS_WIDTH / 2 + PROGRESS_GAP);
|
||||
|
||||
mProgressPath.transform(mTmpMatrix, mScaledTrackPath);
|
||||
float scale = bounds.width() / PATH_SIZE;
|
||||
mProgressPaint.setStrokeWidth(PROGRESS_WIDTH * scale);
|
||||
|
||||
mShadowBitmap = getShadowBitmap(bounds.width(), bounds.height(),
|
||||
(PROGRESS_GAP ) * scale);
|
||||
mPathMeasure.setPath(mScaledTrackPath, true);
|
||||
mTrackLength = mPathMeasure.getLength();
|
||||
|
||||
setInternalProgress(mInternalStateProgress);
|
||||
}
|
||||
|
||||
private Bitmap getShadowBitmap(int width, int height, float shadowRadius) {
|
||||
int key = (width << 16) | height;
|
||||
WeakReference<Bitmap> shadowRef = sShadowCache.get(key);
|
||||
Bitmap shadow = shadowRef != null ? shadowRef.get() : null;
|
||||
if (shadow != null) {
|
||||
return shadow;
|
||||
}
|
||||
shadow = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
|
||||
Canvas c = new Canvas(shadow);
|
||||
mProgressPaint.setShadowLayer(shadowRadius, 0, 0, COLOR_SHADOW);
|
||||
mProgressPaint.setColor(COLOR_TRACK);
|
||||
mProgressPaint.setAlpha(MAX_PAINT_ALPHA);
|
||||
c.drawPath(mScaledTrackPath, mProgressPaint);
|
||||
mProgressPaint.clearShadowLayer();
|
||||
c.setBitmap(null);
|
||||
|
||||
sShadowCache.put(key, new WeakReference<>(shadow));
|
||||
return shadow;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas) {
|
||||
if (mRanFinishAnimation) {
|
||||
super.draw(canvas);
|
||||
return;
|
||||
}
|
||||
|
||||
// Draw track.
|
||||
mProgressPaint.setColor(mIndicatorColor);
|
||||
mProgressPaint.setAlpha(mTrackAlpha);
|
||||
if (mShadowBitmap != null) {
|
||||
canvas.drawBitmap(mShadowBitmap, getBounds().left, getBounds().top, mProgressPaint);
|
||||
}
|
||||
canvas.drawPath(mScaledProgressPath, mProgressPaint);
|
||||
|
||||
int saveCount = canvas.save(Canvas.MATRIX_SAVE_FLAG);
|
||||
Rect bounds = getBounds();
|
||||
|
||||
canvas.scale(mIconScale, mIconScale, bounds.exactCenterX(), bounds.exactCenterY());
|
||||
drawInternal(canvas);
|
||||
canvas.restoreToCount(saveCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the install progress based on the level
|
||||
*/
|
||||
@Override
|
||||
protected boolean onLevelChange(int level) {
|
||||
// Run the animation if we have already been bound.
|
||||
updateInternalState(level * 0.01f, getBounds().width() > 0, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the finish animation if it is has not been run after last call to
|
||||
* {@link #onLevelChange}
|
||||
*/
|
||||
public void maybePerformFinishedAnimation() {
|
||||
// If the drawable was recently initialized, skip the progress animation.
|
||||
if (mInternalStateProgress == 0) {
|
||||
mInternalStateProgress = 1;
|
||||
}
|
||||
updateInternalState(1 + COMPLETE_ANIM_FRACTION, true, true);
|
||||
}
|
||||
|
||||
public boolean hasNotCompleted() {
|
||||
return !mRanFinishAnimation;
|
||||
}
|
||||
|
||||
private void updateInternalState(float finalProgress, boolean shouldAnimate, boolean isFinish) {
|
||||
if (mCurrentAnim != null) {
|
||||
mCurrentAnim.cancel();
|
||||
mCurrentAnim = null;
|
||||
}
|
||||
|
||||
if (Float.compare(finalProgress, mInternalStateProgress) == 0) {
|
||||
return;
|
||||
}
|
||||
if (!shouldAnimate || mRanFinishAnimation) {
|
||||
setInternalProgress(finalProgress);
|
||||
} else {
|
||||
mCurrentAnim = ObjectAnimator.ofFloat(this, INTERNAL_STATE, finalProgress);
|
||||
mCurrentAnim.setDuration(
|
||||
(long) ((finalProgress - mInternalStateProgress) * DURATION_SCALE));
|
||||
mCurrentAnim.setInterpolator(new LinearInterpolator());
|
||||
if (isFinish) {
|
||||
mCurrentAnim.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
mRanFinishAnimation = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
mCurrentAnim.start();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the internal progress and updates the UI accordingly
|
||||
* for progress <= 0:
|
||||
* - icon in the small scale and disabled state
|
||||
* - progress track is visible
|
||||
* - progress bar is not visible
|
||||
* for 0 < progress < 1
|
||||
* - icon in the small scale and disabled state
|
||||
* - progress track is visible
|
||||
* - progress bar is visible with dominant color. Progress bar is drawn as a fraction of
|
||||
* {@link #mScaledTrackPath}.
|
||||
* @see PathMeasure#getSegment(float, float, Path, boolean)
|
||||
* for 1 <= progress < (1 + COMPLETE_ANIM_FRACTION)
|
||||
* - we calculate fraction of progress in the above range
|
||||
* - progress track is drawn with alpha based on fraction
|
||||
* - progress bar is drawn at 100% with alpha based on fraction
|
||||
* - icon is scaled up based on fraction and is drawn in enabled state
|
||||
* for progress >= (1 + COMPLETE_ANIM_FRACTION)
|
||||
* - only icon is drawn in normal state
|
||||
*/
|
||||
private void setInternalProgress(float progress) {
|
||||
mInternalStateProgress = progress;
|
||||
if (progress <= 0) {
|
||||
mIconScale = SMALL_SCALE;
|
||||
mScaledTrackPath.reset();
|
||||
mTrackAlpha = MAX_PAINT_ALPHA;
|
||||
setIsDisabled(true);
|
||||
} else if (mIndicatorColor == 0) {
|
||||
// Update the indicator color
|
||||
mIndicatorColor = getIconPalette().getPreloadProgressColor();
|
||||
}
|
||||
|
||||
if (progress < 1 && progress > 0) {
|
||||
mPathMeasure.getSegment(0, progress * mTrackLength, mScaledProgressPath, true);
|
||||
mIconScale = SMALL_SCALE;
|
||||
mTrackAlpha = MAX_PAINT_ALPHA;
|
||||
setIsDisabled(true);
|
||||
} else if (progress >= 1) {
|
||||
setIsDisabled(false);
|
||||
mScaledTrackPath.set(mScaledProgressPath);
|
||||
float fraction = (progress - 1) / COMPLETE_ANIM_FRACTION;
|
||||
|
||||
if (fraction >= 1) {
|
||||
// Animation has completed
|
||||
mIconScale = 1;
|
||||
mTrackAlpha = 0;
|
||||
} else {
|
||||
mTrackAlpha = Math.round((1 - fraction) * MAX_PAINT_ALPHA);
|
||||
mIconScale = SMALL_SCALE + (1 - SMALL_SCALE) * fraction;
|
||||
}
|
||||
}
|
||||
invalidateSelf();
|
||||
}
|
||||
}
|