From 36579219dea28bb78400e7d5448fa878a513330f Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Fri, 7 Apr 2017 09:21:25 -0700 Subject: [PATCH] Only create one bitmap to clip popup item corners Previously we created a bitmap the size of the entire popup item and drew a rounded rect in it to clip the corners. Now we create a bitmap that is only the size of the rounded corner radius, and rotate and translate it to all four corners to achieve the same clipping. Besides the reduced memory of this approach, it also simplifies things when we reduce the item's height (e.g. when the second to last notification is dismissed), because we no longer have to recreate the background bitmap to match the new size; the translation calculations in dispatchDraw() automatically take the current size into account. Bug: 35869307 Change-Id: I938bbc4bd87479580287426b4197516caf1a64d4 --- .../notification/NotificationItemView.java | 15 +---- .../launcher3/popup/PopupItemView.java | 57 +++++++++++-------- 2 files changed, 33 insertions(+), 39 deletions(-) diff --git a/src/com/android/launcher3/notification/NotificationItemView.java b/src/com/android/launcher3/notification/NotificationItemView.java index c6268e27d2..37b8325ea5 100644 --- a/src/com/android/launcher3/notification/NotificationItemView.java +++ b/src/com/android/launcher3/notification/NotificationItemView.java @@ -17,7 +17,6 @@ package com.android.launcher3.notification; import android.animation.Animator; -import android.animation.AnimatorListenerAdapter; import android.content.Context; import android.graphics.Rect; import android.util.AttributeSet; @@ -74,20 +73,8 @@ public class NotificationItemView extends PopupItemView implements LogContainerP public Animator animateHeightRemoval(int heightToRemove) { final int newHeight = getHeight() - heightToRemove; - Animator heightAnimator = new PillHeightRevealOutlineProvider(mPillRect, + return new PillHeightRevealOutlineProvider(mPillRect, getBackgroundRadius(), newHeight).createRevealAnimator(this, true /* isReversed */); - heightAnimator.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - if (newHeight > 0) { - measure(MeasureSpec.makeMeasureSpec(getWidth(), MeasureSpec.EXACTLY), - MeasureSpec.makeMeasureSpec(newHeight, MeasureSpec.EXACTLY)); - initializeBackgroundClipping(true /* force */); - invalidate(); - } - } - }); - return heightAnimator; } public void updateHeader(int notificationCount) { diff --git a/src/com/android/launcher3/popup/PopupItemView.java b/src/com/android/launcher3/popup/PopupItemView.java index 71daae9364..0853c13d30 100644 --- a/src/com/android/launcher3/popup/PopupItemView.java +++ b/src/com/android/launcher3/popup/PopupItemView.java @@ -21,14 +21,13 @@ import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; import android.content.Context; import android.graphics.Bitmap; -import android.graphics.BitmapShader; import android.graphics.Canvas; +import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Point; import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; import android.graphics.Rect; -import android.graphics.Shader; import android.util.AttributeSet; import android.view.View; import android.widget.FrameLayout; @@ -52,8 +51,9 @@ public abstract class PopupItemView extends FrameLayout protected View mIconView; - private final Paint mBackgroundClipPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG | - Paint.FILTER_BITMAP_FLAG); + private final Paint mBackgroundClipPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG); + private final Matrix mMatrix = new Matrix(); + private Bitmap mRoundedCornerBitmap; public PopupItemView(Context context) { this(context, null, 0); @@ -67,6 +67,14 @@ public abstract class PopupItemView extends FrameLayout super(context, attrs, defStyle); mPillRect = new Rect(); + + // Initialize corner clipping Bitmap and Paint. + int radius = (int) getBackgroundRadius(); + mRoundedCornerBitmap = Bitmap.createBitmap(radius, radius, Bitmap.Config.ALPHA_8); + Canvas canvas = new Canvas(); + canvas.setBitmap(mRoundedCornerBitmap); + canvas.drawArc(0, 0, radius*2, radius*2, 180, 90, true, mBackgroundClipPaint); + mBackgroundClipPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN)); } @Override @@ -81,30 +89,29 @@ public abstract class PopupItemView extends FrameLayout mPillRect.set(0, 0, getMeasuredWidth(), getMeasuredHeight()); } - protected void initializeBackgroundClipping(boolean force) { - if (force || mBackgroundClipPaint.getShader() == null) { - mBackgroundClipPaint.setXfermode(null); - mBackgroundClipPaint.setShader(null); - Bitmap backgroundBitmap = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(), - Bitmap.Config.ALPHA_8); - Canvas canvas = new Canvas(); - canvas.setBitmap(backgroundBitmap); - canvas.drawRoundRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), - getBackgroundRadius(), getBackgroundRadius(), mBackgroundClipPaint); - Shader backgroundClipShader = new BitmapShader(backgroundBitmap, - Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); - mBackgroundClipPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN)); - mBackgroundClipPaint.setShader(backgroundClipShader); - } - } - @Override protected void dispatchDraw(Canvas canvas) { - initializeBackgroundClipping(false /* force */); - int saveCount = canvas.saveLayer(0, 0, getWidth(), getHeight(), null, - Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG); + int saveCount = canvas.saveLayer(0, 0, getWidth(), getHeight(), null); super.dispatchDraw(canvas); - canvas.drawPaint(mBackgroundClipPaint); + + int cornerWidth = mRoundedCornerBitmap.getWidth(); + int cornerHeight = mRoundedCornerBitmap.getHeight(); + // Clip top left corner. + mMatrix.reset(); + canvas.drawBitmap(mRoundedCornerBitmap, mMatrix, mBackgroundClipPaint); + // Clip top right corner. + mMatrix.setRotate(90, cornerWidth / 2, cornerHeight / 2); + mMatrix.postTranslate(canvas.getWidth() - cornerWidth, 0); + canvas.drawBitmap(mRoundedCornerBitmap, mMatrix, mBackgroundClipPaint); + // Clip bottom right corner. + mMatrix.setRotate(180, cornerWidth / 2, cornerHeight / 2); + mMatrix.postTranslate(canvas.getWidth() - cornerWidth, canvas.getHeight() - cornerHeight); + canvas.drawBitmap(mRoundedCornerBitmap, mMatrix, mBackgroundClipPaint); + // Clip bottom left corner. + mMatrix.setRotate(270, cornerWidth / 2, cornerHeight / 2); + mMatrix.postTranslate(0, canvas.getHeight() - cornerHeight); + canvas.drawBitmap(mRoundedCornerBitmap, mMatrix, mBackgroundClipPaint); + canvas.restoreToCount(saveCount); }