blob: 403d856c05a57e94be151b8df5196e7dbcefacf9 [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;
21import android.graphics.Canvas;
22import android.graphics.Paint;
23import android.graphics.Bitmap.Config;
24import android.graphics.PorterDuff.Mode;
25import android.text.Layout;
26import android.util.AttributeSet;
27import android.widget.TextView;
28
29/*
30 * This class is a bit of a hack, designed to speed up long text labels in Launcher. It caches the
31 * text in a TextView to a bitmap and then just draws that Bitmap instead afterward, speeding up
32 * rendering. Marquee scrolling is not currently supported.
33 *
34 */
35public class CachedTextView extends TextView {
36 private Bitmap mCache;
37 private final Paint mCachePaint = new Paint();
38 private final Canvas mCacheCanvas = new Canvas();
39
40 private int mPrevAlpha = -1;
41 private boolean mIsBuildingCache;
42 boolean mIsTextCacheDirty;
43 float mTextCacheLeft;
44 float mTextCacheTop;
45 float mTextCacheScrollX;
46 float mRectLeft, mRectTop;
47 private float mPaddingH = 0;
48 private float mPaddingV = 0;
49 private CharSequence mText;
Michael Jurkac0759f52011-02-03 16:47:14 -080050 private boolean mEnabled = true;
Michael Jurkad63497b2011-01-14 17:56:16 -080051
52 public CachedTextView(Context context) {
53 super(context);
54 }
55
56 public CachedTextView(Context context, AttributeSet attrs) {
57 super(context, attrs);
58 }
59
60 public CachedTextView(Context context, AttributeSet attrs, int defStyle) {
61 super(context, attrs, defStyle);
62 }
63
64 protected int getCacheTopPadding() {
65 return 0;
66 }
67 protected int getCacheLeftPadding() {
68 return 0;
69 }
70 protected int getCacheRightPadding() {
71 return 0;
72 }
73 protected int getCacheBottomPadding() {
74 return 0;
75 }
76
Michael Jurkac0759f52011-02-03 16:47:14 -080077 public void disableCache() {
78 mEnabled = false;
79 }
80
Michael Jurkad63497b2011-01-14 17:56:16 -080081 public void setText(CharSequence text, BufferType type) {
82 super.setText(text, type);
83 mIsTextCacheDirty = true;
84 }
85
86 private void buildAndUpdateCache() {
87 final Layout layout = getLayout();
88 final int left = getCompoundPaddingLeft();
89 final int top = getExtendedPaddingTop();
90 final float prevAlpha = getAlpha();
91
92 mTextCacheLeft = layout.getLineLeft(0) - getCacheLeftPadding();
93 mTextCacheTop = top + layout.getLineTop(0) - mPaddingV - getCacheTopPadding();
94
95 mRectLeft = mScrollX + getLeft();
96 mRectTop = 0;
97 mTextCacheScrollX = mScrollX;
98
99 final float textCacheRight =
100 Math.min(left + layout.getLineRight(0) + mPaddingH, mScrollX + mRight - mLeft) +
101 getCacheRightPadding();
102 final float textCacheBottom = top + layout.getLineBottom(0) + mPaddingV +
103 getCacheBottomPadding();
104 final float xCharWidth = getPaint().measureText("x");
105
106 int width = (int) (textCacheRight - mTextCacheLeft + (2 * xCharWidth));
107 int height = (int) (textCacheBottom - mTextCacheTop);
108
109 if (width != 0 && height != 0) {
110 if (mCache != null) {
111 if (mCache.getWidth() != width || mCache.getHeight() != height) {
112 mCache.recycle();
113 mCache = null;
114 }
115 }
116 if (mCache == null) {
117 mCache = Bitmap.createBitmap(width, height, Config.ARGB_8888);
118 mCacheCanvas.setBitmap(mCache);
119 } else {
120 mCacheCanvas.drawColor(0, Mode.CLEAR);
121 }
122
123 mCacheCanvas.save();
124 mCacheCanvas.translate(-mTextCacheLeft, -mTextCacheTop);
125
126 mIsBuildingCache = true;
127 setAlpha(1.0f);
128 draw(mCacheCanvas);
129 setAlpha(prevAlpha);
130 mIsBuildingCache = false;
131 mCacheCanvas.restore();
132
133 // A hack-- we set the text to be one space (we don't make it empty just to avoid any
134 // potential issues with text measurement, like line height, etc.) so that the text view
135 // doesn't draw it anymore, since it's been cached.
136 mText = getText();
137 setText(" ");
138 }
139 }
140
141 public CharSequence getText() {
142 return (mText == null) ? super.getText() : mText;
143 }
144
145 public void draw(Canvas canvas) {
Michael Jurkac0759f52011-02-03 16:47:14 -0800146 if (mEnabled && mIsTextCacheDirty && !mIsBuildingCache) {
Michael Jurkad63497b2011-01-14 17:56:16 -0800147 buildAndUpdateCache();
148 mIsTextCacheDirty = false;
149 }
150 if (mCache != null && !mIsBuildingCache) {
151 canvas.drawBitmap(mCache, mTextCacheLeft - mTextCacheScrollX + mScrollX,
152 mTextCacheTop, mCachePaint);
153 }
154 super.draw(canvas);
155 }
156
157 protected boolean isBuildingCache() {
158 return mIsBuildingCache;
159 }
160
161 @Override
162 protected boolean onSetAlpha(int alpha) {
163 if (mPrevAlpha != alpha) {
164 mPrevAlpha = alpha;
165 mCachePaint.setAlpha(alpha);
166 super.onSetAlpha(alpha);
167 }
168 return true;
169 }
170}