blob: eaa6636e62ab5fc8f9ff1b9dbb5b691180806150 [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;
50
51 public CachedTextView(Context context) {
52 super(context);
53 }
54
55 public CachedTextView(Context context, AttributeSet attrs) {
56 super(context, attrs);
57 }
58
59 public CachedTextView(Context context, AttributeSet attrs, int defStyle) {
60 super(context, attrs, defStyle);
61 }
62
63 protected int getCacheTopPadding() {
64 return 0;
65 }
66 protected int getCacheLeftPadding() {
67 return 0;
68 }
69 protected int getCacheRightPadding() {
70 return 0;
71 }
72 protected int getCacheBottomPadding() {
73 return 0;
74 }
75
76 public void setText(CharSequence text, BufferType type) {
77 super.setText(text, type);
78 mIsTextCacheDirty = true;
79 }
80
81 private void buildAndUpdateCache() {
82 final Layout layout = getLayout();
83 final int left = getCompoundPaddingLeft();
84 final int top = getExtendedPaddingTop();
85 final float prevAlpha = getAlpha();
86
87 mTextCacheLeft = layout.getLineLeft(0) - getCacheLeftPadding();
88 mTextCacheTop = top + layout.getLineTop(0) - mPaddingV - getCacheTopPadding();
89
90 mRectLeft = mScrollX + getLeft();
91 mRectTop = 0;
92 mTextCacheScrollX = mScrollX;
93
94 final float textCacheRight =
95 Math.min(left + layout.getLineRight(0) + mPaddingH, mScrollX + mRight - mLeft) +
96 getCacheRightPadding();
97 final float textCacheBottom = top + layout.getLineBottom(0) + mPaddingV +
98 getCacheBottomPadding();
99 final float xCharWidth = getPaint().measureText("x");
100
101 int width = (int) (textCacheRight - mTextCacheLeft + (2 * xCharWidth));
102 int height = (int) (textCacheBottom - mTextCacheTop);
103
104 if (width != 0 && height != 0) {
105 if (mCache != null) {
106 if (mCache.getWidth() != width || mCache.getHeight() != height) {
107 mCache.recycle();
108 mCache = null;
109 }
110 }
111 if (mCache == null) {
112 mCache = Bitmap.createBitmap(width, height, Config.ARGB_8888);
113 mCacheCanvas.setBitmap(mCache);
114 } else {
115 mCacheCanvas.drawColor(0, Mode.CLEAR);
116 }
117
118 mCacheCanvas.save();
119 mCacheCanvas.translate(-mTextCacheLeft, -mTextCacheTop);
120
121 mIsBuildingCache = true;
122 setAlpha(1.0f);
123 draw(mCacheCanvas);
124 setAlpha(prevAlpha);
125 mIsBuildingCache = false;
126 mCacheCanvas.restore();
127
128 // A hack-- we set the text to be one space (we don't make it empty just to avoid any
129 // potential issues with text measurement, like line height, etc.) so that the text view
130 // doesn't draw it anymore, since it's been cached.
131 mText = getText();
132 setText(" ");
133 }
134 }
135
136 public CharSequence getText() {
137 return (mText == null) ? super.getText() : mText;
138 }
139
140 public void draw(Canvas canvas) {
141 if (mIsTextCacheDirty && !mIsBuildingCache) {
142 buildAndUpdateCache();
143 mIsTextCacheDirty = false;
144 }
145 if (mCache != null && !mIsBuildingCache) {
146 canvas.drawBitmap(mCache, mTextCacheLeft - mTextCacheScrollX + mScrollX,
147 mTextCacheTop, mCachePaint);
148 }
149 super.draw(canvas);
150 }
151
152 protected boolean isBuildingCache() {
153 return mIsBuildingCache;
154 }
155
156 @Override
157 protected boolean onSetAlpha(int alpha) {
158 if (mPrevAlpha != alpha) {
159 mPrevAlpha = alpha;
160 mCachePaint.setAlpha(alpha);
161 super.onSetAlpha(alpha);
162 }
163 return true;
164 }
165}