diff options
-rw-r--r-- | quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java | 22 | ||||
-rw-r--r-- | res/layout/deep_shortcut.xml | 1 | ||||
-rw-r--r-- | res/layout/system_shortcut.xml | 1 | ||||
-rw-r--r-- | res/layout/widgets_list_row_view.xml | 1 | ||||
-rw-r--r-- | res/values/attrs.xml | 1 | ||||
-rw-r--r-- | src/com/android/launcher3/BubbleTextView.java | 60 | ||||
-rw-r--r-- | src/com/android/launcher3/CellLayout.java | 26 | ||||
-rw-r--r-- | src/com/android/launcher3/ClickShadowView.java | 209 | ||||
-rw-r--r-- | src/com/android/launcher3/FastBitmapDrawable.java | 74 | ||||
-rw-r--r-- | src/com/android/launcher3/allapps/AllAppsContainerView.java | 19 | ||||
-rw-r--r-- | src/com/android/launcher3/graphics/HolographicOutlineHelper.java | 145 | ||||
-rw-r--r-- | src/com/android/launcher3/graphics/PreloadIconDrawable.java | 6 | ||||
-rw-r--r-- | src/com/android/launcher3/model/LoaderTask.java | 25 |
13 files changed, 68 insertions, 522 deletions
diff --git a/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java b/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java index 91f74a6e9..12ae85dbf 100644 --- a/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java +++ b/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java @@ -16,6 +16,7 @@ package com.android.launcher3; +import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY; import static com.android.launcher3.allapps.AllAppsTransitionController.ALL_APPS_PROGRESS; import static com.android.systemui.shared.recents.utilities.Utilities.getNextFrameNumber; import static com.android.systemui.shared.recents.utilities.Utilities.getSurface; @@ -35,6 +36,7 @@ import android.content.pm.PackageManager; import android.content.res.Resources; import android.graphics.Matrix; import android.graphics.Rect; +import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Handler; import android.util.Log; @@ -520,8 +522,14 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag : rect.left; final int viewLocationTop = rect.top; + float startScale = 1f; if (isBubbleTextView && !isDeepShortcutTextView) { - ((BubbleTextView) v).getIconBounds(rect); + BubbleTextView btv = (BubbleTextView) v; + btv.getIconBounds(rect); + Drawable dr = btv.getIcon(); + if (dr instanceof FastBitmapDrawable) { + startScale = ((FastBitmapDrawable) dr).getAnimatedScale(); + } } else { rect.set(0, 0, rect.width(), rect.height()); } @@ -563,14 +571,10 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag float maxScaleX = mDeviceProfile.widthPx / (float) rect.width(); float maxScaleY = mDeviceProfile.heightPx / (float) rect.height(); float scale = Math.max(maxScaleX, maxScaleY); - ObjectAnimator sX = ObjectAnimator.ofFloat(mFloatingView, View.SCALE_X, 1f, scale); - ObjectAnimator sY = ObjectAnimator.ofFloat(mFloatingView, View.SCALE_Y, 1f, scale); - sX.setDuration(500); - sY.setDuration(500); - sX.setInterpolator(Interpolators.EXAGGERATED_EASE); - sY.setInterpolator(Interpolators.EXAGGERATED_EASE); - appIconAnimatorSet.play(sX); - appIconAnimatorSet.play(sY); + ObjectAnimator scaleAnim = ObjectAnimator + .ofFloat(mFloatingView, SCALE_PROPERTY, startScale, scale); + scaleAnim.setDuration(500).setInterpolator(Interpolators.EXAGGERATED_EASE); + appIconAnimatorSet.play(scaleAnim); // Fade out the app icon. ObjectAnimator alpha = ObjectAnimator.ofFloat(mFloatingView, View.ALPHA, 1f, 0f); diff --git a/res/layout/deep_shortcut.xml b/res/layout/deep_shortcut.xml index 4a3db1f13..4a2ad4225 100644 --- a/res/layout/deep_shortcut.xml +++ b/res/layout/deep_shortcut.xml @@ -35,7 +35,6 @@ android:textColor="?android:attr/textColorPrimary" android:fontFamily="sans-serif" launcher:layoutHorizontal="true" - launcher:deferShadowGeneration="true" launcher:iconDisplay="shortcut_popup" launcher:iconSizeOverride="@dimen/deep_shortcut_icon_size" /> diff --git a/res/layout/system_shortcut.xml b/res/layout/system_shortcut.xml index 1888e2254..04f3d027d 100644 --- a/res/layout/system_shortcut.xml +++ b/res/layout/system_shortcut.xml @@ -34,7 +34,6 @@ android:fontFamily="sans-serif" launcher:iconDisplay="shortcut_popup" launcher:layoutHorizontal="true" - launcher:deferShadowGeneration="true" android:focusable="false" /> <View diff --git a/res/layout/widgets_list_row_view.xml b/res/layout/widgets_list_row_view.xml index 4cd03ce05..91baf7a76 100644 --- a/res/layout/widgets_list_row_view.xml +++ b/res/layout/widgets_list_row_view.xml @@ -42,7 +42,6 @@ android:textColor="?android:attr/textColorPrimary" android:textSize="16sp" android:textAlignment="viewStart" - launcher:deferShadowGeneration="true" launcher:iconDisplay="widget_section" launcher:iconSizeOverride="@dimen/widget_section_icon_size" launcher:layoutHorizontal="true" /> diff --git a/res/values/attrs.xml b/res/values/attrs.xml index 1351dfa84..64ca05e3c 100644 --- a/res/values/attrs.xml +++ b/res/values/attrs.xml @@ -44,7 +44,6 @@ <enum name="widget_section" value="3" /> <enum name="shortcut_popup" value="4" /> </attr> - <attr name="deferShadowGeneration" format="boolean" /> <attr name="centerVertically" format="boolean" /> </declare-styleable> diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java index 4f50d1a42..8b6d9f825 100644 --- a/src/com/android/launcher3/BubbleTextView.java +++ b/src/com/android/launcher3/BubbleTextView.java @@ -20,7 +20,6 @@ import android.animation.ObjectAnimator; import android.content.Context; import android.content.res.ColorStateList; import android.content.res.TypedArray; -import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; @@ -37,7 +36,6 @@ import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; import android.view.ViewDebug; -import android.view.ViewParent; import android.widget.TextView; import com.android.launcher3.IconCache.IconLoadRequest; @@ -48,7 +46,6 @@ import com.android.launcher3.badge.BadgeRenderer; import com.android.launcher3.folder.FolderIcon; import com.android.launcher3.folder.FolderIconPreviewVerifier; 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; @@ -73,13 +70,9 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver, private final boolean mCenterVertically; private final CheckLongPressHelper mLongPressHelper; - private final HolographicOutlineHelper mOutlineHelper; private final StylusEventHelper mStylusEventHelper; private final float mSlop; - private Bitmap mPressedBackground; - - private final boolean mDeferShadowGenerationOnTouch; private final boolean mLayoutHorizontal; private final int mIconSize; @ViewDebug.ExportedProperty(category = "launcher") @@ -147,8 +140,6 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver, TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.BubbleTextView, defStyle, 0); mLayoutHorizontal = a.getBoolean(R.styleable.BubbleTextView_layoutHorizontal, false); - mDeferShadowGenerationOnTouch = - a.getBoolean(R.styleable.BubbleTextView_deferShadowGeneration, false); int display = a.getInteger(R.styleable.BubbleTextView_iconDisplay, DISPLAY_WORKSPACE); int defaultIconSize = grid.iconSizePx; @@ -173,7 +164,6 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver, mLongPressHelper = new CheckLongPressHelper(this); mStylusEventHelper = new StylusEventHelper(new SimpleOnStylusPressListener(this), this); - mOutlineHelper = HolographicOutlineHelper.getInstance(getContext()); setAccessibilityDelegate(mLauncher.getAccessibilityDelegate()); } @@ -290,13 +280,6 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver, switch (event.getAction()) { case MotionEvent.ACTION_DOWN: - // So that the pressed outline is visible immediately on setStayPressed(), - // we pre-create it on ACTION_DOWN (it takes a small but perceptible amount of time - // to create it) - if (!mDeferShadowGenerationOnTouch && mPressedBackground == null) { - mPressedBackground = mOutlineHelper.createMediumDropShadow(this); - } - // If we're in a stylus button press, don't check for long press. if (!mStylusEventHelper.inStylusButtonPressed()) { mLongPressHelper.postCheckForLongPress(); @@ -304,12 +287,6 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver, break; case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: - // If we've touched down and up on an item, and it's still not "pressed", then - // destroy the pressed outline - if (!isPressed()) { - mPressedBackground = null; - } - mLongPressHelper.cancelLongPress(); break; case MotionEvent.ACTION_MOVE: @@ -323,22 +300,6 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver, void setStayPressed(boolean stayPressed) { mStayPressed = stayPressed; - if (!stayPressed) { - HolographicOutlineHelper.getInstance(getContext()).recycleShadowBitmap(mPressedBackground); - mPressedBackground = null; - } else { - if (mPressedBackground == null) { - mPressedBackground = mOutlineHelper.createMediumDropShadow(this); - } - } - - // Only show the shadow effect when persistent pressed state is set. - ViewParent parent = getParent(); - if (parent != null && parent.getParent() instanceof BubbleTextShadowHandler) { - ((BubbleTextShadowHandler) parent.getParent()).setPressedIcon( - this, mPressedBackground); - } - refreshDrawableState(); } @@ -355,26 +316,12 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver, } @Override - public boolean onKeyDown(int keyCode, KeyEvent event) { - if (super.onKeyDown(keyCode, event)) { - // Pre-create shadow so show immediately on click. - if (mPressedBackground == null) { - mPressedBackground = mOutlineHelper.createMediumDropShadow(this); - } - return true; - } - return false; - } - - @Override public boolean onKeyUp(int keyCode, KeyEvent event) { // Unlike touch events, keypress event propagate pressed state change immediately, // without waiting for onClickHandler to execute. Disable pressed state changes here // to avoid flickering. mIgnorePressedStateChange = true; boolean result = super.onKeyUp(keyCode, event); - - mPressedBackground = null; mIgnorePressedStateChange = false; refreshDrawableState(); return result; @@ -662,11 +609,4 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver, public int getIconSize() { return mIconSize; } - - /** - * Interface to be implemented by the grand parent to allow click shadow effect. - */ - public interface BubbleTextShadowHandler { - void setPressedIcon(BubbleTextView icon, Bitmap background); - } } diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java index 5e4f67034..734aec302 100644 --- a/src/com/android/launcher3/CellLayout.java +++ b/src/com/android/launcher3/CellLayout.java @@ -21,6 +21,7 @@ import android.animation.AnimatorListenerAdapter; import android.animation.TimeInterpolator; import android.animation.ValueAnimator; import android.animation.ValueAnimator.AnimatorUpdateListener; +import android.annotation.SuppressLint; import android.content.Context; import android.content.res.Resources; import android.content.res.TypedArray; @@ -45,7 +46,6 @@ import android.view.ViewDebug; import android.view.ViewGroup; import android.view.accessibility.AccessibilityEvent; -import com.android.launcher3.BubbleTextView.BubbleTextShadowHandler; import com.android.launcher3.LauncherSettings.Favorites; import com.android.launcher3.accessibility.DragAndDropAccessibilityDelegate; import com.android.launcher3.accessibility.FolderAccessibilityHelper; @@ -70,7 +70,7 @@ import java.util.Collections; import java.util.Comparator; import java.util.Stack; -public class CellLayout extends ViewGroup implements BubbleTextShadowHandler { +public class CellLayout extends ViewGroup { public static final int WORKSPACE_ACCESSIBILITY_DRAG = 2; public static final int FOLDER_ACCESSIBILITY_DRAG = 1; @@ -128,8 +128,6 @@ public class CellLayout extends ViewGroup implements BubbleTextShadowHandler { private int mDragOutlineCurrent = 0; private final Paint mDragOutlinePaint = new Paint(); - private final ClickShadowView mTouchFeedbackView; - @Thunk final ArrayMap<LayoutParams, Animator> mReorderAnimators = new ArrayMap<>(); @Thunk final ArrayMap<View, ReorderPreviewAnimation> mShakeAnimators = new ArrayMap<>(); @@ -285,9 +283,6 @@ public class CellLayout extends ViewGroup implements BubbleTextShadowHandler { mShortcutsAndWidgets.setCellDimensions(mCellWidth, mCellHeight, mCountX, mCountY); mStylusEventHelper = new StylusEventHelper(new SimpleOnStylusPressListener(this), this); - - mTouchFeedbackView = new ClickShadowView(context); - addView(mTouchFeedbackView); addView(mShortcutsAndWidgets); } @@ -384,11 +379,6 @@ public class CellLayout extends ViewGroup implements BubbleTextShadowHandler { return mDropPending; } - @Override - public void setPressedIcon(BubbleTextView icon, Bitmap background) { - mTouchFeedbackView.setPressedIcon(icon, background); - } - void setIsDragOverlapping(boolean isDragOverlapping) { if (mIsDragOverlapping != isDragOverlapping) { mIsDragOverlapping = isDragOverlapping; @@ -785,13 +775,6 @@ public class CellLayout extends ViewGroup implements BubbleTextShadowHandler { throw new RuntimeException("CellLayout cannot have UNSPECIFIED dimensions"); } - // Make the feedback view large enough to hold the blur bitmap. - mTouchFeedbackView.measure( - MeasureSpec.makeMeasureSpec(mCellWidth + mTouchFeedbackView.getExtraSize(), - MeasureSpec.EXACTLY), - MeasureSpec.makeMeasureSpec(mCellHeight + mTouchFeedbackView.getExtraSize(), - MeasureSpec.EXACTLY)); - mShortcutsAndWidgets.measure( MeasureSpec.makeMeasureSpec(newWidth, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(newHeight, MeasureSpec.EXACTLY)); @@ -815,11 +798,7 @@ public class CellLayout extends ViewGroup implements BubbleTextShadowHandler { int top = getPaddingTop(); int bottom = b - t - getPaddingBottom(); - mTouchFeedbackView.layout(left, top, - left + mTouchFeedbackView.getMeasuredWidth(), - top + mTouchFeedbackView.getMeasuredHeight()); mShortcutsAndWidgets.layout(left, top, right, bottom); - // Expand the background drawing bounds by the padding baked into the background drawable mBackground.getPadding(mTempRect); mBackground.setBounds( @@ -1012,6 +991,7 @@ public class CellLayout extends ViewGroup implements BubbleTextShadowHandler { } } + @SuppressLint("StringFormatMatches") public String getItemMoveDescription(int cellX, int cellY) { if (mContainerType == HOTSEAT) { return getContext().getString(R.string.move_to_hotseat_position, diff --git a/src/com/android/launcher3/ClickShadowView.java b/src/com/android/launcher3/ClickShadowView.java deleted file mode 100644 index 5391b4d46..000000000 --- a/src/com/android/launcher3/ClickShadowView.java +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright (C) 2014 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; - -import static com.android.launcher3.FastBitmapDrawable.CLICK_FEEDBACK_DURATION; -import static com.android.launcher3.FastBitmapDrawable.CLICK_FEEDBACK_INTERPOLATOR; -import static com.android.launcher3.LauncherAnimUtils.ELEVATION; -import static com.android.launcher3.graphics.HolographicOutlineHelper.ADAPTIVE_ICON_SHADOW_BITMAP; - -import android.animation.ObjectAnimator; -import android.annotation.TargetApi; -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Outline; -import android.graphics.Paint; -import android.graphics.Rect; -import android.graphics.drawable.AdaptiveIconDrawable; -import android.graphics.drawable.Drawable; -import android.os.Build; -import android.util.Property; -import android.view.View; -import android.view.ViewDebug; -import android.view.ViewGroup; -import android.view.ViewOutlineProvider; - -public class ClickShadowView extends View { - - private static final int SHADOW_SIZE_FACTOR = 3; - private static final int SHADOW_LOW_ALPHA = 30; - private static final int SHADOW_HIGH_ALPHA = 60; - - private static float sAdaptiveIconScaleFactor = 1f; - - private final Paint mPaint; - - @ViewDebug.ExportedProperty(category = "launcher") - private final float mShadowOffset; - @ViewDebug.ExportedProperty(category = "launcher") - private final float mShadowPadding; - - private Bitmap mBitmap; - private ObjectAnimator mAnim; - - private Drawable mAdaptiveIcon; - private ViewOutlineProvider mOutlineProvider; - - public ClickShadowView(Context context) { - super(context); - mPaint = new Paint(Paint.FILTER_BITMAP_FLAG); - mPaint.setColor(Color.BLACK); - - mShadowPadding = getResources().getDimension(R.dimen.blur_size_click_shadow); - mShadowOffset = getResources().getDimension(R.dimen.click_shadow_high_shift); - } - - public static void setAdaptiveIconScaleFactor(float factor) { - sAdaptiveIconScaleFactor = factor; - } - - /** - * @return extra space required by the view to show the shadow. - */ - public int getExtraSize() { - return (int) (SHADOW_SIZE_FACTOR * mShadowPadding); - } - - public void setPressedIcon(BubbleTextView icon, Bitmap background) { - if (icon == null) { - setBitmap(null); - cancelAnim(); - return; - } - if (background == null) { - if (mBitmap == ADAPTIVE_ICON_SHADOW_BITMAP) { - // clear animation shadow - } - setBitmap(null); - cancelAnim(); - icon.setOutlineProvider(null); - } else if (setBitmap(background)) { - if (mBitmap == ADAPTIVE_ICON_SHADOW_BITMAP) { - setupAdaptiveShadow(icon); - cancelAnim(); - startAnim(icon, ELEVATION, - getResources().getDimension(R.dimen.click_shadow_elevation)); - } else { - alignWithIconView(icon); - startAnim(this, ALPHA, 1); - } - } - } - - @TargetApi(Build.VERSION_CODES.O) - private void setupAdaptiveShadow(final BubbleTextView view) { - if (mAdaptiveIcon == null) { - mAdaptiveIcon = new AdaptiveIconDrawable(null, null); - mOutlineProvider = new ViewOutlineProvider() { - @Override - public void getOutline(View view, Outline outline) { - mAdaptiveIcon.getOutline(outline); - } - }; - } - - int iconWidth = view.getRight() - view.getLeft(); - int iconHSpace = iconWidth - view.getCompoundPaddingRight() - view.getCompoundPaddingLeft(); - int drawableWidth = view.getIcon().getBounds().width(); - - Rect bounds = new Rect(); - bounds.left = view.getCompoundPaddingLeft() + (iconHSpace - drawableWidth) / 2; - bounds.right = bounds.left + drawableWidth; - bounds.top = view.getPaddingTop(); - bounds.bottom = bounds.top + view.getIcon().getBounds().height(); - Utilities.scaleRectAboutCenter(bounds, sAdaptiveIconScaleFactor); - - mAdaptiveIcon.setBounds(bounds); - view.setOutlineProvider(mOutlineProvider); - } - - /** - * Applies the new bitmap. - * @return true if the view was invalidated. - */ - private boolean setBitmap(Bitmap b) { - if (b != mBitmap){ - mBitmap = b; - invalidate(); - return true; - } - return false; - } - - @Override - protected void onDraw(Canvas canvas) { - if (mBitmap != null) { - mPaint.setAlpha(SHADOW_LOW_ALPHA); - canvas.drawBitmap(mBitmap, 0, 0, mPaint); - mPaint.setAlpha(SHADOW_HIGH_ALPHA); - canvas.drawBitmap(mBitmap, 0, mShadowOffset, mPaint); - } - } - - private void cancelAnim() { - if (mAnim != null) { - mAnim.cancel(); - mAnim.setCurrentPlayTime(0); - mAnim = null; - } - } - - private void startAnim(View target, Property<View, Float> property, float endValue) { - cancelAnim(); - property.set(target, 0f); - mAnim = ObjectAnimator.ofFloat(target, property, endValue); - mAnim.setDuration(CLICK_FEEDBACK_DURATION) - .setInterpolator(CLICK_FEEDBACK_INTERPOLATOR); - mAnim.start(); - } - - /** - * Aligns the shadow with {@param view} - * Note: {@param view} must be a descendant of my parent. - */ - private void alignWithIconView(BubbleTextView view) { - int[] coords = new int[] {0, 0}; - Utilities.getDescendantCoordRelativeToAncestor( - (ViewGroup) view.getParent(), (View) getParent(), coords, false); - - float leftShift = view.getLeft() + coords[0] - getLeft(); - float topShift = view.getTop() + coords[1] - getTop(); - int iconWidth = view.getRight() - view.getLeft(); - int iconHeight = view.getBottom() - view.getTop(); - int iconHSpace = iconWidth - view.getCompoundPaddingRight() - view.getCompoundPaddingLeft(); - float drawableWidth = view.getIcon().getBounds().width(); - - // Set the bounds to clip against - int clipLeft = (int) Math.max(0, coords[0] - leftShift - mShadowPadding); - int clipTop = (int) Math.max(0, coords[1] - topShift - mShadowPadding) ; - setClipBounds(new Rect(clipLeft, clipTop, clipLeft + iconWidth, clipTop + iconHeight)); - - setTranslationX(leftShift - + view.getCompoundPaddingLeft() * view.getScaleX() - + (iconHSpace - drawableWidth) * view.getScaleX() / 2 /* drawable gap */ - + iconWidth * (1 - view.getScaleX()) / 2 /* gap due to scale */ - - mShadowPadding /* extra shadow size */ - ); - setTranslationY(topShift - + view.getPaddingTop() * view.getScaleY() /* drawable gap */ - + view.getHeight() * (1 - view.getScaleY()) / 2 /* gap due to scale */ - - mShadowPadding /* extra shadow size */ - ); - } -} diff --git a/src/com/android/launcher3/FastBitmapDrawable.java b/src/com/android/launcher3/FastBitmapDrawable.java index c4ec8c9a7..5354edf8f 100644 --- a/src/com/android/launcher3/FastBitmapDrawable.java +++ b/src/com/android/launcher3/FastBitmapDrawable.java @@ -16,8 +16,9 @@ package com.android.launcher3; +import static com.android.launcher3.anim.Interpolators.ACCEL; + import android.animation.ObjectAnimator; -import android.animation.TimeInterpolator; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; @@ -28,9 +29,8 @@ import android.graphics.Paint; import android.graphics.PixelFormat; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; +import android.graphics.Rect; import android.graphics.drawable.Drawable; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; import android.util.Property; import android.util.SparseArray; @@ -38,14 +38,12 @@ import com.android.launcher3.graphics.BitmapInfo; public class FastBitmapDrawable extends Drawable { - private static final float PRESSED_BRIGHTNESS = 100f / 255f; + private static final float PRESSED_SCALE = 1.1f; + private static final float DISABLED_DESATURATION = 1f; private static final float DISABLED_BRIGHTNESS = 0.5f; - public static final TimeInterpolator CLICK_FEEDBACK_INTERPOLATOR = (input) -> - (input < 0.05f) ? (input / 0.05f) : ((input < 0.3f) ? 1 : (1 - input) / 0.7f); - - public static final int CLICK_FEEDBACK_DURATION = 2000; + public static final int CLICK_FEEDBACK_DURATION = 200; // Since we don't need 256^2 values for combinations of both the brightness and saturation, we // reduce the value space to a smaller value V, which reduces the number of cached @@ -66,18 +64,23 @@ public class FastBitmapDrawable extends Drawable { private boolean mIsPressed; private boolean mIsDisabled; - private static final Property<FastBitmapDrawable, Float> BRIGHTNESS - = new Property<FastBitmapDrawable, Float>(Float.TYPE, "brightness") { + // Animator and properties for the fast bitmap drawable's scale + private static final Property<FastBitmapDrawable, Float> SCALE + = new Property<FastBitmapDrawable, Float>(Float.TYPE, "scale") { @Override public Float get(FastBitmapDrawable fastBitmapDrawable) { - return fastBitmapDrawable.getBrightness(); + return fastBitmapDrawable.mScale; } @Override public void set(FastBitmapDrawable fastBitmapDrawable, Float value) { - fastBitmapDrawable.setBrightness(value); + fastBitmapDrawable.mScale = value; + fastBitmapDrawable.invalidateSelf(); } }; + private ObjectAnimator mScaleAnimation; + private float mScale = 1; + // The saturation and brightness are values that are mapped to REDUCED_FILTER_VALUE_SPACE and // as a result, can be used to compose the key for the cached ColorMatrixColorFilters @@ -86,9 +89,6 @@ public class FastBitmapDrawable extends Drawable { private int mAlpha = 255; private int mPrevUpdateKey = Integer.MAX_VALUE; - // Animators for the fast bitmap drawable's brightness - private ObjectAnimator mBrightnessAnimator; - public FastBitmapDrawable(Bitmap b) { this(b, Color.TRANSPARENT); } @@ -108,8 +108,20 @@ public class FastBitmapDrawable extends Drawable { } @Override - public void draw(Canvas canvas) { - canvas.drawBitmap(mBitmap, null, getBounds(), mPaint); + public final void draw(Canvas canvas) { + if (mScaleAnimation != null) { + int count = canvas.save(); + Rect bounds = getBounds(); + canvas.scale(mScale, mScale, bounds.exactCenterX(), bounds.exactCenterY()); + drawInternal(canvas, bounds); + canvas.restoreToCount(count); + } else { + drawInternal(canvas, getBounds()); + } + } + + protected void drawInternal(Canvas canvas, Rect bounds) { + canvas.drawBitmap(mBitmap, null, bounds, mPaint); } @Override @@ -138,6 +150,10 @@ public class FastBitmapDrawable extends Drawable { return mAlpha; } + public float getAnimatedScale() { + return mScaleAnimation == null ? 1 : mScale; + } + @Override public int getIntrinsicWidth() { return mBitmap.getWidth(); @@ -184,19 +200,20 @@ public class FastBitmapDrawable extends Drawable { if (mIsPressed != isPressed) { mIsPressed = isPressed; - if (mBrightnessAnimator != null) { - mBrightnessAnimator.cancel(); + if (mScaleAnimation != null) { + mScaleAnimation.cancel(); + mScaleAnimation = null; } if (mIsPressed) { // Animate when going to pressed state - mBrightnessAnimator = ObjectAnimator.ofFloat( - this, BRIGHTNESS, getExpectedBrightness()); - mBrightnessAnimator.setDuration(CLICK_FEEDBACK_DURATION); - mBrightnessAnimator.setInterpolator(CLICK_FEEDBACK_INTERPOLATOR); - mBrightnessAnimator.start(); + mScaleAnimation = ObjectAnimator.ofFloat(this, SCALE, PRESSED_SCALE); + mScaleAnimation.setDuration(CLICK_FEEDBACK_DURATION); + mScaleAnimation.setInterpolator(ACCEL); + mScaleAnimation.start(); } else { - setBrightness(getExpectedBrightness()); + mScale = 1f; + invalidateSelf(); } return true; } @@ -205,12 +222,7 @@ public class FastBitmapDrawable extends Drawable { private void invalidateDesaturationAndBrightness() { setDesaturation(mIsDisabled ? DISABLED_DESATURATION : 0); - setBrightness(getExpectedBrightness()); - } - - private float getExpectedBrightness() { - return mIsDisabled ? DISABLED_BRIGHTNESS : - (mIsPressed ? PRESSED_BRIGHTNESS : 0); + setBrightness(mIsDisabled ? DISABLED_BRIGHTNESS : 0); } public void setIsDisabled(boolean isDisabled) { diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java index 82bdef977..774ea6512 100644 --- a/src/com/android/launcher3/allapps/AllAppsContainerView.java +++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java @@ -18,7 +18,6 @@ package com.android.launcher3.allapps; import static com.android.launcher3.anim.Interpolators.DEACCEL_2; import android.content.Context; -import android.graphics.Bitmap; import android.graphics.Rect; import android.os.Process; import android.support.annotation.NonNull; @@ -37,9 +36,6 @@ import android.view.ViewGroup; import android.widget.RelativeLayout; import com.android.launcher3.AppInfo; -import com.android.launcher3.BubbleTextView; -import com.android.launcher3.BubbleTextView.BubbleTextShadowHandler; -import com.android.launcher3.ClickShadowView; import com.android.launcher3.DeviceProfile; import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener; import com.android.launcher3.DragSource; @@ -66,11 +62,10 @@ import com.android.launcher3.views.BottomUserEducationView; * The all apps view container. */ public class AllAppsContainerView extends RelativeLayout implements DragSource, - OnLongClickListener, Insettable, BubbleTextShadowHandler, OnDeviceProfileChangeListener { + OnLongClickListener, Insettable, OnDeviceProfileChangeListener { private final Launcher mLauncher; private final AdapterHolder[] mAH; - private final ClickShadowView mTouchFeedbackView; private final ItemInfoMatcher mPersonalMatcher = ItemInfoMatcher.ofUser(Process.myUserHandle()); private final ItemInfoMatcher mWorkMatcher = ItemInfoMatcher.not(mPersonalMatcher); private final AllAppsStore mAllAppsStore = new AllAppsStore(); @@ -100,15 +95,8 @@ public class AllAppsContainerView extends RelativeLayout implements DragSource, mLauncher.addOnDeviceProfileChangeListener(this); mSearchQueryBuilder = new SpannableStringBuilder(); - Selection.setSelection(mSearchQueryBuilder, 0); - mTouchFeedbackView = new ClickShadowView(context); - // Make the feedback view large enough to hold the blur bitmap. - int size = mLauncher.getDeviceProfile().allAppsIconSizePx - + mTouchFeedbackView.getExtraSize(); - addView(mTouchFeedbackView, size, size); - mAH = new AdapterHolder[2]; mAH[AdapterHolder.MAIN] = new AdapterHolder(false /* isWork */); mAH[AdapterHolder.WORK] = new AdapterHolder(true /* isWork */); @@ -165,11 +153,6 @@ public class AllAppsContainerView extends RelativeLayout implements DragSource, } } - @Override - public void setPressedIcon(BubbleTextView icon, Bitmap background) { - mTouchFeedbackView.setPressedIcon(icon, background); - } - /** * Returns whether the view itself will handle the touch event or not. */ diff --git a/src/com/android/launcher3/graphics/HolographicOutlineHelper.java b/src/com/android/launcher3/graphics/HolographicOutlineHelper.java deleted file mode 100644 index ebfe1e765..000000000 --- a/src/com/android/launcher3/graphics/HolographicOutlineHelper.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright (C) 2008 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 static com.android.launcher3.ItemInfoWithIcon.FLAG_ADAPTIVE_ICON; - -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.BlurMaskFilter; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Paint; -import android.graphics.PorterDuff; -import android.graphics.PorterDuffXfermode; -import android.graphics.Rect; -import android.graphics.drawable.Drawable; -import android.util.SparseArray; - -import com.android.launcher3.BubbleTextView; -import com.android.launcher3.ItemInfoWithIcon; -import com.android.launcher3.R; -import com.android.launcher3.uioverrides.UiFactory; - -/** - * Utility class to generate shadow and outline effect, which are used for click feedback - * and drag-n-drop respectively. - */ -public class HolographicOutlineHelper { - - /** - * Bitmap used as shadow for Adaptive icons - */ - public static final Bitmap ADAPTIVE_ICON_SHADOW_BITMAP = - Bitmap.createBitmap(1, 1, Bitmap.Config.ALPHA_8); - - private static HolographicOutlineHelper sInstance; - - private final Canvas mCanvas = new Canvas(); - private final Paint mBlurPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG); - private final Paint mErasePaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG); - - private final float mShadowBitmapShift; - private final BlurMaskFilter mShadowBlurMaskFilter; - - // We have 4 different icon sizes: homescreen, hotseat, folder & all-apps - private final SparseArray<Bitmap> mBitmapCache = new SparseArray<>(4); - - private HolographicOutlineHelper(Context context) { - mShadowBitmapShift = context.getResources().getDimension(R.dimen.blur_size_click_shadow); - mShadowBlurMaskFilter = new BlurMaskFilter(mShadowBitmapShift, BlurMaskFilter.Blur.NORMAL); - mErasePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); - } - - public static HolographicOutlineHelper getInstance(Context context) { - if (sInstance == null) { - sInstance = new HolographicOutlineHelper(context.getApplicationContext()); - } - return sInstance; - } - - public Bitmap createMediumDropShadow(BubbleTextView view) { - if (view.getTag() instanceof ItemInfoWithIcon && - ((((ItemInfoWithIcon) view.getTag()).runtimeStatusFlags & FLAG_ADAPTIVE_ICON) - != 0)) { - return ADAPTIVE_ICON_SHADOW_BITMAP; - } - Drawable drawable = view.getIcon(); - if (drawable == null) { - return null; - } - - float scaleX = view.getScaleX(); - float scaleY = view.getScaleY(); - Rect rect = drawable.getBounds(); - - int bitmapWidth = (int) (rect.width() * scaleX); - int bitmapHeight = (int) (rect.height() * scaleY); - if (bitmapHeight <= 0 || bitmapWidth <= 0) { - return null; - } - - int key = (bitmapWidth << 16) | bitmapHeight; - Bitmap cache = mBitmapCache.get(key); - if (cache == null) { - cache = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.ALPHA_8); - mCanvas.setBitmap(cache); - mBitmapCache.put(key, cache); - } else { - mCanvas.setBitmap(cache); - mCanvas.drawColor(Color.BLACK, PorterDuff.Mode.CLEAR); - } - - int saveCount = mCanvas.save(); - mCanvas.scale(scaleX, scaleY); - mCanvas.translate(-rect.left, -rect.top); - if (!UiFactory.USE_HARDWARE_BITMAP) { - // TODO: Outline generation requires alpha extraction, which is costly for - // hardware bitmaps. Instead use canvas layer operations once its available. - drawable.draw(mCanvas); - } - mCanvas.restoreToCount(saveCount); - mCanvas.setBitmap(null); - - mBlurPaint.setMaskFilter(mShadowBlurMaskFilter); - - int extraSize = (int) (2 * mShadowBitmapShift); - - int resultWidth = bitmapWidth + extraSize; - int resultHeight = bitmapHeight + extraSize; - key = (resultWidth << 16) | resultHeight; - Bitmap result = mBitmapCache.get(key); - if (result == null) { - result = Bitmap.createBitmap(resultWidth, resultHeight, Bitmap.Config.ALPHA_8); - mCanvas.setBitmap(result); - } else { - // Use put instead of delete, to avoid unnecessary shrinking of cache array - mBitmapCache.put(key, null); - mCanvas.setBitmap(result); - mCanvas.drawColor(Color.BLACK, PorterDuff.Mode.CLEAR); - } - mCanvas.drawBitmap(cache, mShadowBitmapShift, mShadowBitmapShift, mBlurPaint); - mCanvas.setBitmap(null); - return result; - } - - public void recycleShadowBitmap(Bitmap bitmap) { - if (bitmap != null && bitmap != ADAPTIVE_ICON_SHADOW_BITMAP) { - mBitmapCache.put((bitmap.getWidth() << 16) | bitmap.getHeight(), bitmap); - } - } -} diff --git a/src/com/android/launcher3/graphics/PreloadIconDrawable.java b/src/com/android/launcher3/graphics/PreloadIconDrawable.java index ea55ba441..bc7526830 100644 --- a/src/com/android/launcher3/graphics/PreloadIconDrawable.java +++ b/src/com/android/launcher3/graphics/PreloadIconDrawable.java @@ -162,7 +162,7 @@ public class PreloadIconDrawable extends FastBitmapDrawable { } @Override - public void draw(Canvas canvas) { + public void drawInternal(Canvas canvas, Rect bounds) { if (mRanFinishAnimation) { super.draw(canvas); return; @@ -172,13 +172,11 @@ public class PreloadIconDrawable extends FastBitmapDrawable { mProgressPaint.setColor(mIndicatorColor); mProgressPaint.setAlpha(mTrackAlpha); if (mShadowBitmap != null) { - canvas.drawBitmap(mShadowBitmap, getBounds().left, getBounds().top, mProgressPaint); + canvas.drawBitmap(mShadowBitmap, bounds.left, bounds.top, mProgressPaint); } canvas.drawPath(mScaledProgressPath, mProgressPaint); int saveCount = canvas.save(); - Rect bounds = getBounds(); - canvas.scale(mIconScale, mIconScale, bounds.exactCenterX(), bounds.exactCenterY()); super.draw(canvas); canvas.restoreToCount(saveCount); diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java index c61505014..9d1ff8316 100644 --- a/src/com/android/launcher3/model/LoaderTask.java +++ b/src/com/android/launcher3/model/LoaderTask.java @@ -16,6 +16,11 @@ package com.android.launcher3.model; +import static com.android.launcher3.ItemInfoWithIcon.FLAG_DISABLED_LOCKED_USER; +import static com.android.launcher3.ItemInfoWithIcon.FLAG_DISABLED_SAFEMODE; +import static com.android.launcher3.ItemInfoWithIcon.FLAG_DISABLED_SUSPENDED; +import static com.android.launcher3.folder.ClippedFolderIconLayoutRule.MAX_NUM_ITEMS_IN_PREVIEW; + import android.appwidget.AppWidgetProviderInfo; import android.content.ComponentName; import android.content.ContentResolver; @@ -25,7 +30,6 @@ import android.content.IntentFilter; import android.content.pm.LauncherActivityInfo; import android.content.pm.PackageInstaller; import android.graphics.Bitmap; -import android.graphics.drawable.AdaptiveIconDrawable; import android.os.Handler; import android.os.Process; import android.os.UserHandle; @@ -36,7 +40,6 @@ import android.util.MutableInt; import com.android.launcher3.AllAppsList; import com.android.launcher3.AppInfo; -import com.android.launcher3.ClickShadowView; import com.android.launcher3.FolderInfo; import com.android.launcher3.IconCache; import com.android.launcher3.InstallShortcutReceiver; @@ -75,11 +78,6 @@ import java.util.List; import java.util.Map; import java.util.concurrent.CancellationException; -import static com.android.launcher3.ItemInfoWithIcon.FLAG_DISABLED_LOCKED_USER; -import static com.android.launcher3.ItemInfoWithIcon.FLAG_DISABLED_SAFEMODE; -import static com.android.launcher3.ItemInfoWithIcon.FLAG_DISABLED_SUSPENDED; -import static com.android.launcher3.folder.ClippedFolderIconLayoutRule.MAX_NUM_ITEMS_IN_PREVIEW; - /** * Runnable for the thread that loads the contents of the launcher: * - workspace icons @@ -146,9 +144,7 @@ public class LoaderTask implements Runnable { TraceHelper.beginSection(TAG); try (LauncherModel.LoaderTransaction transaction = mApp.getModel().beginLoader(this)) { - TraceHelper.partitionSection(TAG, "step 1.1: loading UI resources"); - loadUiResources(); - TraceHelper.partitionSection(TAG, "step 1.2: loading workspace"); + TraceHelper.partitionSection(TAG, "step 1.1: loading workspace"); loadWorkspace(); verifyNotStopped(); @@ -211,15 +207,6 @@ public class LoaderTask implements Runnable { this.notify(); } - public void loadUiResources() { - if (Utilities.ATLEAST_OREO) { - LauncherIcons li = LauncherIcons.obtain(mApp.getContext()); - ClickShadowView.setAdaptiveIconScaleFactor(li.getNormalizer() - .getScale(new AdaptiveIconDrawable(null, null), null, null, null)); - li.recycle(); - } - } - private void loadWorkspace() { final Context context = mApp.getContext(); final ContentResolver contentResolver = context.getContentResolver(); |