Caching icon labels to bitmaps for better performance
Change-Id: I78a3c116c1103b5b994a47f2cfcff18c0a9b31b8
diff --git a/src/com/android/launcher2/BubbleTextView.java b/src/com/android/launcher2/BubbleTextView.java
index f4a3d44..6039307 100644
--- a/src/com/android/launcher2/BubbleTextView.java
+++ b/src/com/android/launcher2/BubbleTextView.java
@@ -19,6 +19,7 @@
import android.widget.TextView;
import android.content.Context;
import android.util.AttributeSet;
+import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
@@ -32,7 +33,7 @@
* because we want to make the bubble taller than the text and TextView's clip is
* too aggressive.
*/
-public class BubbleTextView extends TextView {
+public class BubbleTextView extends CacheableTextView {
static final float CORNER_RADIUS = 8.0f;
static final float PADDING_H = 5.0f;
static final float PADDING_V = 1.0f;
@@ -77,6 +78,18 @@
mPaddingV = PADDING_V * scale;
}
+ public void applyFromShortcutInfo(ShortcutInfo info, IconCache iconCache) {
+ Bitmap b = info.getIcon(iconCache);
+
+ setCompoundDrawablesWithIntrinsicBounds(null,
+ new FastBitmapDrawable(b),
+ null, null);
+ setText(info.title);
+ buildAndEnableCache();
+ setTag(info);
+
+ }
+
@Override
protected boolean setFrame(int left, int top, int right, int bottom) {
if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
@@ -129,7 +142,9 @@
top + layout.getLineTop(0) - mPaddingV,
Math.min(left + layout.getLineRight(0) + mPaddingH, mScrollX + mRight - mLeft),
top + layout.getLineBottom(0) + mPaddingV);
- canvas.drawRoundRect(rect, mCornerRadius, mCornerRadius, mPaint);
+ // TEMPORARILY DISABLE DRAWING ROUND RECT -- re-enable this when we tweak CacheableTextView
+ // to support padding so we can capture the "rounded" edges
+ //canvas.drawRoundRect(rect, mCornerRadius, mCornerRadius, mPaint);
super.draw(canvas);
}
diff --git a/src/com/android/launcher2/CacheableTextView.java b/src/com/android/launcher2/CacheableTextView.java
new file mode 100644
index 0000000..26eafa9
--- /dev/null
+++ b/src/com/android/launcher2/CacheableTextView.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2010 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.launcher2;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Bitmap.Config;
+import android.text.Layout;
+import android.util.AttributeSet;
+import android.widget.TextView;
+
+/*
+ * This class is a bit of a hack, designed to speed up long text labels in Launcher. It caches the
+ * text in a TextView to a bitmap and then just draws that Bitmap instead afterward, speeding up
+ * rendering. Marquee scrolling is not currently supported.
+ *
+ */
+public class CacheableTextView extends TextView {
+ private Bitmap mCache;
+ private final Paint mCachePaint = new Paint();
+
+ private int mPrevAlpha = -1;
+ private boolean mIsBuildingCache;
+ boolean mWaitingToGenerateCache;
+ float mTextCacheLeft;
+ float mTextCacheTop;
+ float mTextCacheScrollX;
+ float mRectLeft, mRectTop;
+ private float mPaddingH = 0;
+ private float mPaddingV = 0;
+
+ public CacheableTextView(Context context) {
+ super(context);
+ }
+
+ public CacheableTextView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public CacheableTextView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ public void buildAndEnableCache() {
+ if (getLayout() == null) {
+ mWaitingToGenerateCache = true;
+ return;
+ }
+
+ final Layout layout = getLayout();
+
+ final int left = getCompoundPaddingLeft();
+ final int top = getExtendedPaddingTop();
+ mTextCacheLeft = layout.getLineLeft(0);
+ mTextCacheTop = top + layout.getLineTop(0) - mPaddingV;
+
+ mRectLeft = mScrollX + getLeft();
+ mRectTop = 0;
+ mTextCacheScrollX = mScrollX;
+
+ final float textCacheRight =
+ Math.min(left + layout.getLineRight(0) + mPaddingH, mScrollX + mRight - mLeft);
+ final float textCacheBottom = top + layout.getLineBottom(0) + mPaddingV;
+
+ mCache = Bitmap.createBitmap((int) (textCacheRight - mTextCacheLeft),
+ (int) (textCacheBottom - mTextCacheTop), Config.ARGB_8888);
+ Canvas c = new Canvas(mCache);
+ c.translate(-mTextCacheLeft, -mTextCacheTop);
+
+ mIsBuildingCache = true;
+ float alpha = getAlpha();
+ setAlpha(1.0f);
+ draw(c);
+ setAlpha(alpha);
+ mIsBuildingCache = false;
+ mCachePaint.setFilterBitmap(true);
+
+ // A hack-- we set the text to be one space (we don't make it empty just to avoid any
+ // potential issues with text measurement, like line height, etc.) so that the text view
+ // doesn't draw it anymore, since it's been cached. We have to manually rebuild
+ // the cache whenever the text is changed (which is never in Launcher)
+ setText(" ");
+ }
+
+ public void draw(Canvas canvas) {
+ if (mWaitingToGenerateCache && !mIsBuildingCache) {
+ buildAndEnableCache();
+ mWaitingToGenerateCache = false;
+ }
+ if (mCache != null) {
+ canvas.drawBitmap(mCache, mTextCacheLeft - mTextCacheScrollX + mScrollX,
+ mTextCacheTop, mCachePaint);
+ }
+ super.draw(canvas);
+ }
+
+ @Override
+ protected boolean onSetAlpha(int alpha) {
+ if (mPrevAlpha != alpha) {
+ mPrevAlpha = alpha;
+ mCachePaint.setAlpha(alpha);
+ super.onSetAlpha(alpha);
+ }
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java
index 033ccc3..eacaef9 100644
--- a/src/com/android/launcher2/Launcher.java
+++ b/src/com/android/launcher2/Launcher.java
@@ -1038,17 +1038,9 @@
* @return A View inflated from layoutResId.
*/
View createShortcut(int layoutResId, ViewGroup parent, ShortcutInfo info) {
- TextView favorite = (TextView) mInflater.inflate(layoutResId, parent, false);
-
- Bitmap b = info.getIcon(mIconCache);
-
- favorite.setCompoundDrawablesWithIntrinsicBounds(null,
- new FastBitmapDrawable(b),
- null, null);
- favorite.setText(info.title);
- favorite.setTag(info);
+ BubbleTextView favorite = (BubbleTextView) mInflater.inflate(layoutResId, parent, false);
+ favorite.applyFromShortcutInfo(info, mIconCache);
favorite.setOnClickListener(this);
-
return favorite;
}
diff --git a/src/com/android/launcher2/PagedViewIcon.java b/src/com/android/launcher2/PagedViewIcon.java
index b9b9b37..9e48351 100644
--- a/src/com/android/launcher2/PagedViewIcon.java
+++ b/src/com/android/launcher2/PagedViewIcon.java
@@ -39,7 +39,7 @@
* An icon on a PagedView, specifically for items in the launcher's paged view (with compound
* drawables on the top).
*/
-public class PagedViewIcon extends TextView implements Checkable {
+public class PagedViewIcon extends CacheableTextView implements Checkable {
private static final String TAG = "PagedViewIcon";
// holographic outline
@@ -138,6 +138,7 @@
mIcon = info.iconBitmap;
setCompoundDrawablesWithIntrinsicBounds(null, new FastBitmapDrawable(mIcon), null, null);
setText(info.title);
+ buildAndEnableCache();
setTag(info);
queueHolographicOutlineCreation();
@@ -153,6 +154,7 @@
modelIconCache.getFullResIcon(info, packageManager), mContext);
setCompoundDrawablesWithIntrinsicBounds(null, new FastBitmapDrawable(mIcon), null, null);
setText(info.loadLabel(packageManager));
+ buildAndEnableCache();
setTag(info);
queueHolographicOutlineCreation();