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