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