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