PagedViewIcon.java revision c0759f5090d9539d82ddc944b9f2da767c36b251
1/* 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 com.android.launcher.R; 20 21import android.animation.ObjectAnimator; 22import android.content.Context; 23import android.content.pm.PackageManager; 24import android.content.pm.ResolveInfo; 25import android.content.res.Resources; 26import android.content.res.TypedArray; 27import android.graphics.Bitmap; 28import android.graphics.Canvas; 29import android.graphics.Paint; 30import android.os.Handler; 31import android.os.HandlerThread; 32import android.os.Message; 33import android.util.AttributeSet; 34import android.widget.Checkable; 35import android.widget.TextView; 36 37 38 39/** 40 * An icon on a PagedView, specifically for items in the launcher's paged view (with compound 41 * drawables on the top). 42 */ 43public class PagedViewIcon extends CachedTextView implements Checkable { 44 private static final String TAG = "PagedViewIcon"; 45 46 // holographic outline 47 private final Paint mPaint = new Paint(); 48 private static HolographicOutlineHelper sHolographicOutlineHelper; 49 private Bitmap mCheckedOutline; 50 private Bitmap mHolographicOutline; 51 private Bitmap mIcon; 52 53 private PagedViewIconCache.Key mIconCacheKey; 54 private PagedViewIconCache mIconCache; 55 56 private int mAlpha = 255; 57 private int mHolographicAlpha; 58 59 private boolean mIsChecked; 60 private ObjectAnimator mCheckedAlphaAnimator; 61 private float mCheckedAlpha = 1.0f; 62 private int mCheckedFadeInDuration; 63 private int mCheckedFadeOutDuration; 64 65 // Highlight colors 66 private int mHoloBlurColor; 67 private int mHoloOutlineColor; 68 69 HolographicPagedViewIcon mHolographicOutlineView; 70 71 private static final HandlerThread sWorkerThread = new HandlerThread("pagedviewicon-helper"); 72 static { 73 sWorkerThread.start(); 74 } 75 76 private static final int MESSAGE_CREATE_HOLOGRAPHIC_OUTLINE = 1; 77 78 private static final Handler sWorker = new Handler(sWorkerThread.getLooper()) { 79 private DeferredHandler mHandler = new DeferredHandler(); 80 private Paint mPaint = new Paint(); 81 public void handleMessage(Message msg) { 82 final PagedViewIcon icon = (PagedViewIcon) msg.obj; 83 84 final Bitmap holographicOutline = Bitmap.createBitmap( 85 icon.mIcon.getWidth(), icon.mIcon.getHeight(), Bitmap.Config.ARGB_8888); 86 Canvas holographicOutlineCanvas = new Canvas(holographicOutline); 87 holographicOutlineCanvas.drawBitmap(icon.mIcon, 0, 0, mPaint); 88 89 sHolographicOutlineHelper.applyThickExpensiveOutlineWithBlur(holographicOutline, 90 holographicOutlineCanvas, icon.mHoloBlurColor, icon.mHoloOutlineColor); 91 92 mHandler.post(new Runnable() { 93 public void run() { 94 icon.mHolographicOutline = holographicOutline; 95 icon.mIconCache.addOutline(icon.mIconCacheKey, holographicOutline); 96 icon.getHolographicOutlineView().invalidate(); 97 } 98 }); 99 } 100 }; 101 102 public PagedViewIcon(Context context) { 103 this(context, null); 104 } 105 106 public PagedViewIcon(Context context, AttributeSet attrs) { 107 this(context, attrs, 0); 108 } 109 110 public PagedViewIcon(Context context, AttributeSet attrs, int defStyle) { 111 super(context, attrs, defStyle); 112 113 TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PagedViewIcon, defStyle, 0); 114 mHoloBlurColor = a.getColor(R.styleable.PagedViewIcon_blurColor, 0); 115 mHoloOutlineColor = a.getColor(R.styleable.PagedViewIcon_outlineColor, 0); 116 a.recycle(); 117 118 if (sHolographicOutlineHelper == null) { 119 sHolographicOutlineHelper = new HolographicOutlineHelper(); 120 } 121 122 // Set up fade in/out constants 123 final Resources r = context.getResources(); 124 final int alpha = r.getInteger(R.integer.icon_allAppsCustomizeFadeAlpha); 125 if (alpha > 0) { 126 mCheckedAlpha = r.getInteger(R.integer.icon_allAppsCustomizeFadeAlpha) / 256.0f; 127 mCheckedFadeInDuration = r.getInteger(R.integer.icon_allAppsCustomizeFadeInTime); 128 mCheckedFadeOutDuration = r.getInteger(R.integer.icon_allAppsCustomizeFadeOutTime); 129 } 130 131 setFocusable(true); 132 setBackgroundDrawable(null); 133 mHolographicOutlineView = new HolographicPagedViewIcon(context, this); 134 } 135 136 protected HolographicPagedViewIcon getHolographicOutlineView() { 137 return mHolographicOutlineView; 138 } 139 140 protected Bitmap getHolographicOutline() { 141 return mHolographicOutline; 142 } 143 144 private void queueHolographicOutlineCreation() { 145 // Generate the outline in the background 146 if (mHolographicOutline == null) { 147 Message m = sWorker.obtainMessage(MESSAGE_CREATE_HOLOGRAPHIC_OUTLINE); 148 m.obj = this; 149 sWorker.sendMessage(m); 150 } 151 } 152 153 public void applyFromApplicationInfo(ApplicationInfo info, PagedViewIconCache cache, 154 boolean scaleUp, boolean createHolographicOutlines) { 155 mIcon = info.iconBitmap; 156 setCompoundDrawablesWithIntrinsicBounds(null, new FastBitmapDrawable(mIcon), null, null); 157 setText(info.title); 158 setTag(info); 159 160 if (createHolographicOutlines) { 161 mIconCache = cache; 162 mIconCacheKey = new PagedViewIconCache.Key(info); 163 mHolographicOutline = mIconCache.getOutline(mIconCacheKey); 164 queueHolographicOutlineCreation(); 165 } 166 } 167 168 public void applyFromResolveInfo(ResolveInfo info, PackageManager packageManager, 169 PagedViewIconCache cache, IconCache modelIconCache, boolean createHolographicOutlines) { 170 mIcon = Utilities.createIconBitmap( 171 modelIconCache.getFullResIcon(info, packageManager), mContext); 172 setCompoundDrawablesWithIntrinsicBounds(null, new FastBitmapDrawable(mIcon), null, null); 173 setText(info.loadLabel(packageManager)); 174 setTag(info); 175 176 if (createHolographicOutlines) { 177 mIconCache = cache; 178 mIconCacheKey = new PagedViewIconCache.Key(info); 179 mHolographicOutline = mIconCache.getOutline(mIconCacheKey); 180 queueHolographicOutlineCreation(); 181 } 182 } 183 184 @Override 185 public void setAlpha(float alpha) { 186 final float viewAlpha = sHolographicOutlineHelper.viewAlphaInterpolator(alpha); 187 final float holographicAlpha = sHolographicOutlineHelper.highlightAlphaInterpolator(alpha); 188 int newViewAlpha = (int) (viewAlpha * 255); 189 int newHolographicAlpha = (int) (holographicAlpha * 255); 190 if ((mAlpha != newViewAlpha) || (mHolographicAlpha != newHolographicAlpha)) { 191 mAlpha = newViewAlpha; 192 mHolographicAlpha = newHolographicAlpha; 193 super.setAlpha(viewAlpha); 194 } 195 } 196 197 public void invalidateCheckedImage() { 198 if (mCheckedOutline != null) { 199 mCheckedOutline.recycle(); 200 mCheckedOutline = null; 201 } 202 } 203 204 @Override 205 protected void onDraw(Canvas canvas) { 206 if (mAlpha > 0) { 207 super.onDraw(canvas); 208 } 209 210 Bitmap overlay = null; 211 212 // draw any blended overlays 213 if (mCheckedOutline == null) { 214 if (mHolographicOutline != null && mHolographicAlpha > 0) { 215 mPaint.setAlpha(mHolographicAlpha); 216 overlay = mHolographicOutline; 217 } 218 } else { 219 mPaint.setAlpha(255); 220 overlay = mCheckedOutline; 221 } 222 223 if (overlay != null) { 224 final int offset = getScrollX(); 225 final int compoundPaddingLeft = getCompoundPaddingLeft(); 226 final int compoundPaddingRight = getCompoundPaddingRight(); 227 int hspace = getWidth() - compoundPaddingRight - compoundPaddingLeft; 228 canvas.drawBitmap(overlay, 229 offset + compoundPaddingLeft + (hspace - overlay.getWidth()) / 2, 230 mPaddingTop, 231 mPaint); 232 } 233 } 234 235 @Override 236 public void onDetachedFromWindow() { 237 super.onDetachedFromWindow(); 238 sWorker.removeMessages(MESSAGE_CREATE_HOLOGRAPHIC_OUTLINE, this); 239 } 240 241 @Override 242 public boolean isChecked() { 243 return mIsChecked; 244 } 245 246 @Override 247 public void setChecked(boolean checked) { 248 if (mIsChecked != checked) { 249 mIsChecked = checked; 250 251 float alpha; 252 int duration; 253 if (mIsChecked) { 254 alpha = mCheckedAlpha; 255 duration = mCheckedFadeInDuration; 256 } else { 257 alpha = 1.0f; 258 duration = mCheckedFadeOutDuration; 259 } 260 261 // Initialize the animator 262 if (mCheckedAlphaAnimator != null) { 263 mCheckedAlphaAnimator.cancel(); 264 } 265 mCheckedAlphaAnimator = ObjectAnimator.ofFloat(this, "alpha", getAlpha(), alpha); 266 mCheckedAlphaAnimator.setDuration(duration); 267 mCheckedAlphaAnimator.start(); 268 269 invalidate(); 270 } 271 } 272 273 @Override 274 public void toggle() { 275 setChecked(!mIsChecked); 276 } 277} 278