blob: ac2cc3b5c4fe8d7557c3a4356ba769ec5d1185d8 [file] [log] [blame]
/*
* 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.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.graphics.drawable.Drawable;
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 CachedTextView extends TextView {
private Bitmap mCache;
private final Paint mCachePaint = new Paint();
private final Canvas mCacheCanvas = new Canvas();
private int mPrevAlpha = -1;
private boolean mIsBuildingCache;
boolean mIsTextCacheDirty;
float mTextCacheLeft;
float mTextCacheTop;
float mTextCacheScrollX;
float mRectLeft, mRectTop;
private float mPaddingH = 0;
private float mPaddingV = 0;
private CharSequence mText;
private boolean mEnabled = true;
public CachedTextView(Context context) {
super(context);
}
public CachedTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CachedTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
protected int getCacheTopPadding() {
return 0;
}
protected int getCacheLeftPadding() {
return 0;
}
protected int getCacheRightPadding() {
return 0;
}
protected int getCacheBottomPadding() {
return 0;
}
public void disableCache() {
mEnabled = false;
}
public void setText(CharSequence text, BufferType type) {
super.setText(text, type);
mIsTextCacheDirty = true;
}
private void buildAndUpdateCache() {
final Layout layout = getLayout();
final int left = getCompoundPaddingLeft();
final int top = getExtendedPaddingTop();
final float prevAlpha = getAlpha();
mTextCacheLeft = layout.getLineLeft(0) - getCacheLeftPadding();
mTextCacheTop = top + layout.getLineTop(0) - mPaddingV - getCacheTopPadding();
mRectLeft = mScrollX + getLeft();
mRectTop = 0;
mTextCacheScrollX = mScrollX;
final float textCacheRight =
Math.min(left + layout.getLineRight(0) + mPaddingH, mScrollX + mRight - mLeft) +
getCacheRightPadding();
final float textCacheBottom = top + layout.getLineBottom(0) + mPaddingV +
getCacheBottomPadding();
final float xCharWidth = getPaint().measureText("x");
int width = (int) (textCacheRight - mTextCacheLeft + (2 * xCharWidth));
int height = (int) (textCacheBottom - mTextCacheTop);
if (width > 0 && height > 0) {
if (mCache != null) {
if (mCache.getWidth() != width || mCache.getHeight() != height) {
mCache.recycle();
mCache = null;
}
}
if (mCache == null) {
mCache = Bitmap.createBitmap(width, height, Config.ARGB_8888);
mCacheCanvas.setBitmap(mCache);
} else {
mCacheCanvas.drawColor(0, Mode.CLEAR);
}
mCacheCanvas.save();
mCacheCanvas.translate(-mTextCacheLeft, -mTextCacheTop);
mIsBuildingCache = true;
setAlpha(1.0f);
draw(mCacheCanvas);
setAlpha(prevAlpha);
mIsBuildingCache = false;
mCacheCanvas.restore();
// 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.
mText = getText();
setText(" ");
}
}
public CharSequence getText() {
return (mText == null) ? super.getText() : mText;
}
public void draw(Canvas canvas) {
if (mEnabled && mIsTextCacheDirty && !mIsBuildingCache) {
buildAndUpdateCache();
mIsTextCacheDirty = false;
}
if (mCache != null && !mIsBuildingCache) {
canvas.drawBitmap(mCache, mTextCacheLeft - mTextCacheScrollX + mScrollX,
mTextCacheTop, mCachePaint);
}
super.draw(canvas);
}
protected boolean isBuildingCache() {
return mIsBuildingCache;
}
@Override
protected boolean onSetAlpha(int alpha) {
if (mPrevAlpha != alpha) {
mPrevAlpha = alpha;
mCachePaint.setAlpha(alpha);
// We manually update the drawables alpha since the default TextView implementation may
// not do this if there is a background set (which we may due to the focus bg)
final Drawable[] dr = getCompoundDrawables();
for (int i = 0; i < dr.length; ++i) {
if (dr[i] != null) {
dr[i].mutate().setAlpha(alpha);
}
}
super.onSetAlpha(alpha);
}
return true;
}
}