blob: d0f6dd804f8cceb5f8c38b55352b6cc167fcc92c [file] [log] [blame]
Michael Jurkad63497b2011-01-14 17:56:16 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.launcher2;
18
19import android.content.Context;
20import android.graphics.Bitmap;
Winson Chung97d85d22011-04-13 11:27:36 -070021import android.graphics.Bitmap.Config;
Michael Jurkad63497b2011-01-14 17:56:16 -080022import android.graphics.Canvas;
23import android.graphics.Paint;
Michael Jurkad63497b2011-01-14 17:56:16 -080024import android.graphics.PorterDuff.Mode;
Winson Chung97d85d22011-04-13 11:27:36 -070025import android.graphics.drawable.Drawable;
Michael Jurkad63497b2011-01-14 17:56:16 -080026import android.text.Layout;
27import android.util.AttributeSet;
28import android.widget.TextView;
29
30/*
31 * This class is a bit of a hack, designed to speed up long text labels in Launcher. It caches the
32 * text in a TextView to a bitmap and then just draws that Bitmap instead afterward, speeding up
33 * rendering. Marquee scrolling is not currently supported.
34 *
35 */
36public class CachedTextView extends TextView {
37 private Bitmap mCache;
38 private final Paint mCachePaint = new Paint();
39 private final Canvas mCacheCanvas = new Canvas();
40
41 private int mPrevAlpha = -1;
42 private boolean mIsBuildingCache;
43 boolean mIsTextCacheDirty;
44 float mTextCacheLeft;
45 float mTextCacheTop;
46 float mTextCacheScrollX;
47 float mRectLeft, mRectTop;
48 private float mPaddingH = 0;
49 private float mPaddingV = 0;
50 private CharSequence mText;
Michael Jurkac0759f52011-02-03 16:47:14 -080051 private boolean mEnabled = true;
Michael Jurkad63497b2011-01-14 17:56:16 -080052
53 public CachedTextView(Context context) {
54 super(context);
55 }
56
57 public CachedTextView(Context context, AttributeSet attrs) {
58 super(context, attrs);
59 }
60
61 public CachedTextView(Context context, AttributeSet attrs, int defStyle) {
62 super(context, attrs, defStyle);
63 }
64
65 protected int getCacheTopPadding() {
66 return 0;
67 }
68 protected int getCacheLeftPadding() {
69 return 0;
70 }
71 protected int getCacheRightPadding() {
72 return 0;
73 }
74 protected int getCacheBottomPadding() {
75 return 0;
76 }
77
Michael Jurkac0759f52011-02-03 16:47:14 -080078 public void disableCache() {
79 mEnabled = false;
80 }
81
Michael Jurkad63497b2011-01-14 17:56:16 -080082 public void setText(CharSequence text, BufferType type) {
83 super.setText(text, type);
84 mIsTextCacheDirty = true;
85 }
86
87 private void buildAndUpdateCache() {
88 final Layout layout = getLayout();
89 final int left = getCompoundPaddingLeft();
90 final int top = getExtendedPaddingTop();
91 final float prevAlpha = getAlpha();
92
93 mTextCacheLeft = layout.getLineLeft(0) - getCacheLeftPadding();
94 mTextCacheTop = top + layout.getLineTop(0) - mPaddingV - getCacheTopPadding();
95
96 mRectLeft = mScrollX + getLeft();
97 mRectTop = 0;
98 mTextCacheScrollX = mScrollX;
99
100 final float textCacheRight =
101 Math.min(left + layout.getLineRight(0) + mPaddingH, mScrollX + mRight - mLeft) +
102 getCacheRightPadding();
103 final float textCacheBottom = top + layout.getLineBottom(0) + mPaddingV +
104 getCacheBottomPadding();
105 final float xCharWidth = getPaint().measureText("x");
106
107 int width = (int) (textCacheRight - mTextCacheLeft + (2 * xCharWidth));
108 int height = (int) (textCacheBottom - mTextCacheTop);
109
110 if (width != 0 && height != 0) {
111 if (mCache != null) {
112 if (mCache.getWidth() != width || mCache.getHeight() != height) {
113 mCache.recycle();
114 mCache = null;
115 }
116 }
117 if (mCache == null) {
118 mCache = Bitmap.createBitmap(width, height, Config.ARGB_8888);
119 mCacheCanvas.setBitmap(mCache);
120 } else {
121 mCacheCanvas.drawColor(0, Mode.CLEAR);
122 }
123
124 mCacheCanvas.save();
125 mCacheCanvas.translate(-mTextCacheLeft, -mTextCacheTop);
126
127 mIsBuildingCache = true;
128 setAlpha(1.0f);
129 draw(mCacheCanvas);
130 setAlpha(prevAlpha);
131 mIsBuildingCache = false;
132 mCacheCanvas.restore();
133
134 // A hack-- we set the text to be one space (we don't make it empty just to avoid any
135 // potential issues with text measurement, like line height, etc.) so that the text view
136 // doesn't draw it anymore, since it's been cached.
137 mText = getText();
138 setText(" ");
139 }
140 }
141
142 public CharSequence getText() {
143 return (mText == null) ? super.getText() : mText;
144 }
145
146 public void draw(Canvas canvas) {
Michael Jurkac0759f52011-02-03 16:47:14 -0800147 if (mEnabled && mIsTextCacheDirty && !mIsBuildingCache) {
Michael Jurkad63497b2011-01-14 17:56:16 -0800148 buildAndUpdateCache();
149 mIsTextCacheDirty = false;
150 }
151 if (mCache != null && !mIsBuildingCache) {
152 canvas.drawBitmap(mCache, mTextCacheLeft - mTextCacheScrollX + mScrollX,
153 mTextCacheTop, mCachePaint);
154 }
155 super.draw(canvas);
156 }
157
158 protected boolean isBuildingCache() {
159 return mIsBuildingCache;
160 }
161
162 @Override
163 protected boolean onSetAlpha(int alpha) {
164 if (mPrevAlpha != alpha) {
165 mPrevAlpha = alpha;
166 mCachePaint.setAlpha(alpha);
Winson Chung97d85d22011-04-13 11:27:36 -0700167
168 // We manually update the drawables alpha since the default TextView implementation may
169 // not do this if there is a background set (which we may due to the focus bg)
170 final Drawable[] dr = getCompoundDrawables();
171 for (int i = 0; i < dr.length; ++i) {
172 if (dr[i] != null) {
173 dr[i].mutate().setAlpha(alpha);
174 }
175 }
176
Michael Jurkad63497b2011-01-14 17:56:16 -0800177 super.onSetAlpha(alpha);
178 }
179 return true;
180 }
181}