From 1d62b8a7fc75bba57e9af721c12f4d6b3e080c98 Mon Sep 17 00:00:00 2001 From: Peter Schiller Date: Wed, 29 Jun 2016 09:46:43 -0700 Subject: [PATCH] Adding shadow to fast scroll indicator Bug: 29761848 Change-Id: I9db7e73fb6b8c703be21a6c3f9e2a50253a48ec7 --- .../BaseRecyclerViewFastScrollPopup.java | 43 +++++++++++++++++-- .../launcher3/HolographicOutlineHelper.java | 32 +++++++++----- 2 files changed, 61 insertions(+), 14 deletions(-) diff --git a/src/com/android/launcher3/BaseRecyclerViewFastScrollPopup.java b/src/com/android/launcher3/BaseRecyclerViewFastScrollPopup.java index baf96fe0e7..1e714b3b22 100644 --- a/src/com/android/launcher3/BaseRecyclerViewFastScrollPopup.java +++ b/src/com/android/launcher3/BaseRecyclerViewFastScrollPopup.java @@ -18,6 +18,7 @@ package com.android.launcher3; import android.animation.Animator; import android.animation.ObjectAnimator; import android.content.res.Resources; +import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; @@ -31,9 +32,16 @@ public class BaseRecyclerViewFastScrollPopup { private static final float FAST_SCROLL_OVERLAY_Y_OFFSET_FACTOR = 1.5f; + private static final int SHADOW_INSET = 6; + private static final int SHADOW_SHIFT_Y = 4; + private static final float SHADOW_ALPHA_MULTIPLIER = 0.6f; + private Resources mRes; private BaseRecyclerView mRv; + private Bitmap mShadow; + private Paint mShadowPaint; + private Drawable mBg; // The absolute bounds of the fast scroller bg private Rect mBgBounds = new Rect(); @@ -52,13 +60,20 @@ public class BaseRecyclerViewFastScrollPopup { public BaseRecyclerViewFastScrollPopup(BaseRecyclerView rv, Resources res) { mRes = res; mRv = rv; + mBgOriginalSize = res.getDimensionPixelSize(R.dimen.container_fastscroll_popup_size); mBg = rv.getContext().getDrawable(R.drawable.container_fastscroll_popup_bg); mBg.setBounds(0, 0, mBgOriginalSize, mBgOriginalSize); + mTextPaint = new Paint(); mTextPaint.setColor(Color.WHITE); mTextPaint.setAntiAlias(true); mTextPaint.setTextSize(res.getDimensionPixelSize(R.dimen.container_fastscroll_popup_text_size)); + + mShadowPaint = new Paint(); + mShadowPaint.setAntiAlias(true); + mShadowPaint.setFilterBitmap(true); + mShadowPaint.setDither(true); } /** @@ -75,6 +90,7 @@ public class BaseRecyclerViewFastScrollPopup { /** * Updates the bounds for the fast scroller. + * * @return the invalidation rect for this update. */ public Rect updateFastScrollerBounds(int lastTouchY) { @@ -98,6 +114,10 @@ public class BaseRecyclerViewFastScrollPopup { mBgBounds.top = Math.max(edgePadding, Math.min(mBgBounds.top, mRv.getHeight() - edgePadding - bgHeight)); mBgBounds.bottom = mBgBounds.top + bgHeight; + + // Generate a bitmap for a shadow matching these bounds + mShadow = HolographicOutlineHelper.obtain( + mRv.getContext()).createMediumDropShadow(mBg, false /* shouldCache */); } else { mBgBounds.setEmpty(); } @@ -138,17 +158,32 @@ public class BaseRecyclerViewFastScrollPopup { public void draw(Canvas c) { if (isVisible()) { - // Draw the fast scroller popup + // Determine the alpha and prepare the canvas + final int alpha = (int) (mAlpha * 255); int restoreCount = c.save(Canvas.MATRIX_SAVE_FLAG); c.translate(mBgBounds.left, mBgBounds.top); mTmpRect.set(mBgBounds); mTmpRect.offsetTo(0, 0); + + // Expand the rect (with a negative inset), translate it, and draw the shadow + if (mShadow != null) { + mTmpRect.inset(-SHADOW_INSET * 2, -SHADOW_INSET * 2); + mTmpRect.offset(0, SHADOW_SHIFT_Y); + mShadowPaint.setAlpha((int) (alpha * SHADOW_ALPHA_MULTIPLIER)); + c.drawBitmap(mShadow, null, mTmpRect, mShadowPaint); + mTmpRect.inset(SHADOW_INSET * 2, SHADOW_INSET * 2); + mTmpRect.offset(0, -SHADOW_SHIFT_Y); + } + + // Draw the background mBg.setBounds(mTmpRect); - mBg.setAlpha((int) (mAlpha * 255)); + mBg.setAlpha(alpha); mBg.draw(c); - mTextPaint.setAlpha((int) (mAlpha * 255)); + + // Draw the text + mTextPaint.setAlpha(alpha); c.drawText(mSectionName, (mBgBounds.width() - mTextBounds.width()) / 2, - mBgBounds.height() - (mBgBounds.height() - mTextBounds.height()) / 2, + mBgBounds.height() - (mBgBounds.height() / 2) - mTextBounds.exactCenterY(), mTextPaint); c.restoreToCount(restoreCount); } diff --git a/src/com/android/launcher3/HolographicOutlineHelper.java b/src/com/android/launcher3/HolographicOutlineHelper.java index 6ea06e976c..1cff8ef16a 100644 --- a/src/com/android/launcher3/HolographicOutlineHelper.java +++ b/src/com/android/launcher3/HolographicOutlineHelper.java @@ -83,6 +83,7 @@ public class HolographicOutlineHelper { int outlineColor) { applyExpensiveOutlineWithBlur(srcDst, srcDstCanvas, color, outlineColor, true); } + void applyExpensiveOutlineWithBlur(Bitmap srcDst, Canvas srcDstCanvas, int color, int outlineColor, boolean clipAlpha) { @@ -151,33 +152,44 @@ public class HolographicOutlineHelper { } Bitmap createMediumDropShadow(BubbleTextView view) { - Drawable icon = view.getIcon(); - if (icon == null) { + return createMediumDropShadow(view.getIcon(), view.getScaleX(), view.getScaleY(), true); + } + + Bitmap createMediumDropShadow(Drawable drawable, boolean shouldCache) { + return createMediumDropShadow(drawable, 1f, 1f, shouldCache); + } + + Bitmap createMediumDropShadow(Drawable drawable, float scaleX, float scaleY, + boolean shouldCache) { + if (drawable == null) { return null; } - Rect rect = icon.getBounds(); + Rect rect = drawable.getBounds(); - int bitmapWidth = (int) (rect.width() * view.getScaleX()); - int bitmapHeight = (int) (rect.height() * view.getScaleY()); + 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); + Bitmap cache = shouldCache ? mBitmapCache.get(key) : null; if (cache == null) { cache = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.ALPHA_8); mCanvas.setBitmap(cache); - mBitmapCache.put(key, cache); + + if (shouldCache) { + mBitmapCache.put(key, cache); + } } else { mCanvas.setBitmap(cache); mCanvas.drawColor(Color.BLACK, PorterDuff.Mode.CLEAR); } int saveCount = mCanvas.save(); - mCanvas.scale(view.getScaleX(), view.getScaleY()); + mCanvas.scale(scaleX, scaleY); mCanvas.translate(-rect.left, -rect.top); - icon.draw(mCanvas); + drawable.draw(mCanvas); mCanvas.restoreToCount(saveCount); mCanvas.setBitmap(null); @@ -188,7 +200,7 @@ public class HolographicOutlineHelper { int resultWidth = bitmapWidth + extraSize; int resultHeight = bitmapHeight + extraSize; key = (resultWidth << 16) | resultHeight; - Bitmap result = mBitmapCache.get(key); + Bitmap result = shouldCache ? mBitmapCache.get(key) : null; if (result == null) { result = Bitmap.createBitmap(resultWidth, resultHeight, Bitmap.Config.ALPHA_8); mCanvas.setBitmap(result);