blob: 8ee9b616d0c466f793694d1016f8120d2f7fafc0 [file] [log] [blame]
Jim Millerf2dfc352012-08-29 18:42:21 -07001/*
2 * Copyright (C) 2012 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
Jim Miller5ecd8112013-01-09 18:50:26 -080017package com.android.keyguard;
Jim Millerf2dfc352012-08-29 18:42:21 -070018
Adam Cohene3643132012-10-28 18:29:17 -070019import android.animation.Animator;
20import android.animation.ObjectAnimator;
21import android.animation.PropertyValuesHolder;
Michael Jurka1254f2f2012-10-25 11:44:31 -070022import android.appwidget.AppWidgetHostView;
Michael Jurka67a871d2012-11-01 18:26:01 -070023import android.appwidget.AppWidgetManager;
Jim Millerf2dfc352012-08-29 18:42:21 -070024import android.content.Context;
25import android.content.res.Resources;
26import android.graphics.Canvas;
Adam Cohen61cd69c2012-10-02 21:42:54 -070027import android.graphics.LinearGradient;
Jim Millerf2dfc352012-08-29 18:42:21 -070028import android.graphics.Paint;
29import android.graphics.PorterDuff;
30import android.graphics.PorterDuffXfermode;
31import android.graphics.Rect;
Adam Cohen61cd69c2012-10-02 21:42:54 -070032import android.graphics.Shader;
Jim Millerd6523da2012-10-21 16:47:02 -070033import android.graphics.drawable.Drawable;
John Spurlock37d84ae2012-11-04 11:11:47 -050034import android.os.Handler;
Jim Millerf2dfc352012-08-29 18:42:21 -070035import android.util.AttributeSet;
Jim Miller5d2da7132012-10-02 18:38:09 -070036import android.view.MotionEvent;
Jim Millerd6523da2012-10-21 16:47:02 -070037import android.view.View;
Jim Millerf2dfc352012-08-29 18:42:21 -070038import android.widget.FrameLayout;
39
Jim Millerf2dfc352012-08-29 18:42:21 -070040public class KeyguardWidgetFrame extends FrameLayout {
41 private final static PorterDuffXfermode sAddBlendMode =
42 new PorterDuffXfermode(PorterDuff.Mode.ADD);
Jim Millerf2dfc352012-08-29 18:42:21 -070043
Adam Powellcfc30862012-10-29 18:21:31 -070044 static final float OUTLINE_ALPHA_MULTIPLIER = 0.6f;
Winson Chungf3b9ec82012-11-01 14:48:51 -070045 static final int HOVER_OVER_DELETE_DROP_TARGET_OVERLAY_COLOR = 0x99FF0000;
46
47 // Temporarily disable this for the time being until we know why the gfx is messing up
48 static final boolean ENABLE_HOVER_OVER_DELETE_DROP_TARGET_OVERLAY = true;
Adam Powellcfc30862012-10-29 18:21:31 -070049
Adam Cohen61cd69c2012-10-02 21:42:54 -070050 private int mGradientColor;
51 private LinearGradient mForegroundGradient;
52 private LinearGradient mLeftToRightGradient;
53 private LinearGradient mRightToLeftGradient;
54 private Paint mGradientPaint = new Paint();
55 boolean mLeftToRight = true;
56
Adam Cohen66b9fb1662012-09-05 16:23:58 -070057 private float mOverScrollAmount = 0f;
Jim Millerf2dfc352012-08-29 18:42:21 -070058 private final Rect mForegroundRect = new Rect();
59 private int mForegroundAlpha = 0;
Jim Miller19a52672012-10-23 19:52:04 -070060 private CheckLongPressHelper mLongPressHelper;
Adam Cohene3643132012-10-28 18:29:17 -070061 private Animator mFrameFade;
62 private boolean mIsSmall = false;
John Spurlock37d84ae2012-11-04 11:11:47 -050063 private Handler mWorkerHandler;
Jim Millerf2dfc352012-08-29 18:42:21 -070064
Jim Millerd6523da2012-10-21 16:47:02 -070065 private float mBackgroundAlpha;
Adam Cohenf9048cd2012-10-27 16:36:10 -070066 private float mContentAlpha;
Adam Cohen6fb841f2012-10-24 13:15:38 -070067 private float mBackgroundAlphaMultiplier = 1.0f;
Jim Millerd6523da2012-10-21 16:47:02 -070068 private Drawable mBackgroundDrawable;
69 private Rect mBackgroundRect = new Rect();
Adam Cohen4ddcd572012-11-01 17:36:32 -070070
71 // These variables are all needed in order to size things properly before we're actually
72 // measured.
Adam Cohen5be14de2012-10-30 11:19:48 -070073 private int mSmallWidgetHeight;
Adam Cohen4ddcd572012-11-01 17:36:32 -070074 private int mSmallFrameHeight;
75 private boolean mWidgetLockedSmall = false;
76 private int mMaxChallengeTop = -1;
Adam Cohen5d47a8d2012-11-03 19:10:56 -070077 private int mFrameStrokeAdjustment;
Adam Cohenc276e822012-11-08 13:01:08 -080078 private boolean mPerformAppWidgetSizeUpdateOnBootComplete;
Adam Cohen4ddcd572012-11-01 17:36:32 -070079
80 // This will hold the width value before we've actually been measured
81 private int mFrameHeight;
Jim Millerd6523da2012-10-21 16:47:02 -070082
Winson Chungf3b9ec82012-11-01 14:48:51 -070083 private boolean mIsHoveringOverDeleteDropTarget;
84
Adam Cohene3643132012-10-28 18:29:17 -070085 // Multiple callers may try and adjust the alpha of the frame. When a caller shows
86 // the outlines, we give that caller control, and nobody else can fade them out.
87 // This prevents animation conflicts.
88 private Object mBgAlphaController;
89
Jim Millerf2dfc352012-08-29 18:42:21 -070090 public KeyguardWidgetFrame(Context context) {
91 this(context, null, 0);
92 }
93
94 public KeyguardWidgetFrame(Context context, AttributeSet attrs) {
95 this(context, attrs, 0);
96 }
97
98 public KeyguardWidgetFrame(Context context, AttributeSet attrs, int defStyle) {
99 super(context, attrs, defStyle);
Jim Miller5d2da7132012-10-02 18:38:09 -0700100
Jim Miller19a52672012-10-23 19:52:04 -0700101 mLongPressHelper = new CheckLongPressHelper(this);
Jim Miller5d2da7132012-10-02 18:38:09 -0700102
Adam Cohen7ffa8c02012-10-01 19:03:46 -0700103 Resources res = context.getResources();
Jim Millerd6523da2012-10-21 16:47:02 -0700104 // TODO: this padding should really correspond to the padding embedded in the background
Jim Miller022554e2012-10-22 19:03:06 -0700105 // drawable (ie. outlines).
Adam Cohen5d47a8d2012-11-03 19:10:56 -0700106 float density = res.getDisplayMetrics().density;
Jim Millerd6523da2012-10-21 16:47:02 -0700107 int padding = (int) (res.getDisplayMetrics().density * 8);
108 setPadding(padding, padding, padding, padding);
109
Adam Cohend51700b32012-11-07 16:26:46 -0800110 mFrameStrokeAdjustment = 2 + (int) (2 * density);
Adam Cohen5d47a8d2012-11-03 19:10:56 -0700111
Adam Cohen6f72b1c2012-11-05 15:20:30 -0800112 // This will be overriden on phones based on the current security mode, however on tablets
113 // we need to specify a height.
114 mSmallWidgetHeight =
Jim Miller5ecd8112013-01-09 18:50:26 -0800115 res.getDimensionPixelSize(R.dimen.kg_small_widget_height);
Adam Cohend51700b32012-11-07 16:26:46 -0800116 mBackgroundDrawable = res.getDrawable(R.drawable.kg_widget_bg_padded);
Jim Miller5ecd8112013-01-09 18:50:26 -0800117 mGradientColor = res.getColor(R.color.kg_widget_pager_gradient);
Adam Cohen61cd69c2012-10-02 21:42:54 -0700118 mGradientPaint.setXfermode(sAddBlendMode);
Jim Millerf2dfc352012-08-29 18:42:21 -0700119 }
120
Jim Miller19a52672012-10-23 19:52:04 -0700121 @Override
Adam Cohene3643132012-10-28 18:29:17 -0700122 protected void onDetachedFromWindow() {
Adam Cohenc276e822012-11-08 13:01:08 -0800123 super.onDetachedFromWindow();
Adam Cohene3643132012-10-28 18:29:17 -0700124 cancelLongPress();
Adam Cohenc276e822012-11-08 13:01:08 -0800125 KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mUpdateMonitorCallbacks);
126
Adam Cohene3643132012-10-28 18:29:17 -0700127 }
128
Adam Cohenc276e822012-11-08 13:01:08 -0800129 @Override
130 protected void onAttachedToWindow() {
131 super.onAttachedToWindow();
132 KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateMonitorCallbacks);
133 }
134
135 private KeyguardUpdateMonitorCallback mUpdateMonitorCallbacks =
136 new KeyguardUpdateMonitorCallback() {
137 @Override
138 public void onBootCompleted() {
139 if (mPerformAppWidgetSizeUpdateOnBootComplete) {
140 performAppWidgetSizeCallbacksIfNecessary();
141 mPerformAppWidgetSizeUpdateOnBootComplete = false;
142 }
143 }
144 };
145
Winson Chungf3b9ec82012-11-01 14:48:51 -0700146 void setIsHoveringOverDeleteDropTarget(boolean isHovering) {
147 if (ENABLE_HOVER_OVER_DELETE_DROP_TARGET_OVERLAY) {
148 if (mIsHoveringOverDeleteDropTarget != isHovering) {
149 mIsHoveringOverDeleteDropTarget = isHovering;
Jim Miller1962e262013-09-25 17:08:48 -0700150 int resId = isHovering ? R.string.keyguard_accessibility_delete_widget_start
151 : R.string.keyguard_accessibility_delete_widget_end;
152 String text = getContext().getResources().getString(resId, getContentDescription());
153 announceForAccessibility(text);
Winson Chungf3b9ec82012-11-01 14:48:51 -0700154 invalidate();
155 }
156 }
157 }
158
Adam Cohene3643132012-10-28 18:29:17 -0700159 @Override
Jim Miller19a52672012-10-23 19:52:04 -0700160 public boolean onInterceptTouchEvent(MotionEvent ev) {
161 // Watch for longpress events at this level to make sure
162 // users can always pick up this widget
163 switch (ev.getAction()) {
164 case MotionEvent.ACTION_DOWN:
165 mLongPressHelper.postCheckForLongPress(ev);
166 break;
167 case MotionEvent.ACTION_MOVE:
168 mLongPressHelper.onMove(ev);
169 break;
170 case MotionEvent.ACTION_POINTER_DOWN:
171 case MotionEvent.ACTION_UP:
172 case MotionEvent.ACTION_CANCEL:
173 mLongPressHelper.cancelLongPress();
174 break;
175 }
176
177 // Otherwise continue letting touch events fall through to children
178 return false;
Jim Miller5d2da7132012-10-02 18:38:09 -0700179 }
180
181 @Override
Jim Miller19a52672012-10-23 19:52:04 -0700182 public boolean onTouchEvent(MotionEvent ev) {
183 // Watch for longpress events at this level to make sure
184 // users can always pick up this widget
185 switch (ev.getAction()) {
186 case MotionEvent.ACTION_MOVE:
187 mLongPressHelper.onMove(ev);
188 break;
189 case MotionEvent.ACTION_POINTER_DOWN:
190 case MotionEvent.ACTION_UP:
191 case MotionEvent.ACTION_CANCEL:
192 mLongPressHelper.cancelLongPress();
193 break;
Jim Miller5d2da7132012-10-02 18:38:09 -0700194 }
Jim Miller19a52672012-10-23 19:52:04 -0700195
196 // We return true here to ensure that we will get cancel / up signal
197 // even if none of our children have requested touch.
Jim Miller5d2da7132012-10-02 18:38:09 -0700198 return true;
199 }
200
Jim Millerf2dfc352012-08-29 18:42:21 -0700201 @Override
Jim Miller19a52672012-10-23 19:52:04 -0700202 public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
203 super.requestDisallowInterceptTouchEvent(disallowIntercept);
204 cancelLongPress();
205 }
206
207 @Override
208 public void cancelLongPress() {
209 super.cancelLongPress();
210 mLongPressHelper.cancelLongPress();
211 }
212
Adam Cohenf9048cd2012-10-27 16:36:10 -0700213
214 private void drawGradientOverlay(Canvas c) {
215 mGradientPaint.setShader(mForegroundGradient);
216 mGradientPaint.setAlpha(mForegroundAlpha);
217 c.drawRect(mForegroundRect, mGradientPaint);
218 }
219
Winson Chungf3b9ec82012-11-01 14:48:51 -0700220 private void drawHoveringOverDeleteOverlay(Canvas c) {
221 if (mIsHoveringOverDeleteDropTarget) {
222 c.drawColor(HOVER_OVER_DELETE_DROP_TARGET_OVERLAY_COLOR);
223 }
224 }
225
Adam Cohenf9048cd2012-10-27 16:36:10 -0700226 protected void drawBg(Canvas canvas) {
227 if (mBackgroundAlpha > 0.0f) {
228 Drawable bg = mBackgroundDrawable;
229
230 bg.setAlpha((int) (mBackgroundAlpha * mBackgroundAlphaMultiplier * 255));
231 bg.setBounds(mBackgroundRect);
232 bg.draw(canvas);
233 }
234 }
235
Jim Miller19a52672012-10-23 19:52:04 -0700236 @Override
Jim Millerf2dfc352012-08-29 18:42:21 -0700237 protected void dispatchDraw(Canvas canvas) {
Winson Chungf3b9ec82012-11-01 14:48:51 -0700238 if (ENABLE_HOVER_OVER_DELETE_DROP_TARGET_OVERLAY) {
239 canvas.save();
240 }
Jim Millerd6523da2012-10-21 16:47:02 -0700241 drawBg(canvas);
Jim Millerf2dfc352012-08-29 18:42:21 -0700242 super.dispatchDraw(canvas);
Adam Cohen61cd69c2012-10-02 21:42:54 -0700243 drawGradientOverlay(canvas);
Winson Chungf3b9ec82012-11-01 14:48:51 -0700244 if (ENABLE_HOVER_OVER_DELETE_DROP_TARGET_OVERLAY) {
245 drawHoveringOverDeleteOverlay(canvas);
246 canvas.restore();
247 }
Adam Cohen61cd69c2012-10-02 21:42:54 -0700248 }
249
Jim Millerd6523da2012-10-21 16:47:02 -0700250 /**
251 * Because this view has fading outlines, it is essential that we enable hardware
252 * layers on the content (child) so that updating the alpha of the outlines doesn't
253 * result in the content layer being recreated.
254 */
255 public void enableHardwareLayersForContent() {
256 View widget = getContent();
John Reck0a4079e2013-09-30 15:31:31 -0700257 if (widget != null && widget.isHardwareAccelerated()) {
Jim Millerd6523da2012-10-21 16:47:02 -0700258 widget.setLayerType(LAYER_TYPE_HARDWARE, null);
259 }
260 }
261
262 /**
263 * Because this view has fading outlines, it is essential that we enable hardware
264 * layers on the content (child) so that updating the alpha of the outlines doesn't
265 * result in the content layer being recreated.
266 */
267 public void disableHardwareLayersForContent() {
268 View widget = getContent();
269 if (widget != null) {
270 widget.setLayerType(LAYER_TYPE_NONE, null);
271 }
272 }
273
274 public View getContent() {
275 return getChildAt(0);
276 }
277
Michael Jurka1254f2f2012-10-25 11:44:31 -0700278 public int getContentAppWidgetId() {
279 View content = getContent();
280 if (content instanceof AppWidgetHostView) {
281 return ((AppWidgetHostView) content).getAppWidgetId();
Michael Jurka67a871d2012-11-01 18:26:01 -0700282 } else if (content instanceof KeyguardStatusView) {
Michael Jurka1254f2f2012-10-25 11:44:31 -0700283 return ((KeyguardStatusView) content).getAppWidgetId();
Michael Jurka67a871d2012-11-01 18:26:01 -0700284 } else {
285 return AppWidgetManager.INVALID_APPWIDGET_ID;
Michael Jurka1254f2f2012-10-25 11:44:31 -0700286 }
287 }
288
Jim Millerd6523da2012-10-21 16:47:02 -0700289 public float getBackgroundAlpha() {
290 return mBackgroundAlpha;
291 }
292
293 public void setBackgroundAlphaMultiplier(float multiplier) {
Adam Cohenf9048cd2012-10-27 16:36:10 -0700294 if (Float.compare(mBackgroundAlphaMultiplier, multiplier) != 0) {
Jim Millerd6523da2012-10-21 16:47:02 -0700295 mBackgroundAlphaMultiplier = multiplier;
296 invalidate();
297 }
298 }
299
300 public float getBackgroundAlphaMultiplier() {
301 return mBackgroundAlphaMultiplier;
302 }
303
304 public void setBackgroundAlpha(float alpha) {
Adam Cohenf9048cd2012-10-27 16:36:10 -0700305 if (Float.compare(mBackgroundAlpha, alpha) != 0) {
Jim Millerd6523da2012-10-21 16:47:02 -0700306 mBackgroundAlpha = alpha;
307 invalidate();
308 }
309 }
310
Adam Cohenf9048cd2012-10-27 16:36:10 -0700311 public float getContentAlpha() {
312 return mContentAlpha;
313 }
314
Adam Cohen6fb841f2012-10-24 13:15:38 -0700315 public void setContentAlpha(float alpha) {
Adam Cohenf9048cd2012-10-27 16:36:10 -0700316 mContentAlpha = alpha;
Adam Cohen6fb841f2012-10-24 13:15:38 -0700317 View content = getContent();
318 if (content != null) {
319 content.setAlpha(alpha);
320 }
321 }
322
Jim Millerd6523da2012-10-21 16:47:02 -0700323 /**
324 * Depending on whether the security is up, the widget size needs to change
Jim Miller1962e262013-09-25 17:08:48 -0700325 *
Jim Millerd6523da2012-10-21 16:47:02 -0700326 * @param height The height of the widget, -1 for full height
327 */
Adam Cohene3643132012-10-28 18:29:17 -0700328 private void setWidgetHeight(int height) {
Jim Millerd6523da2012-10-21 16:47:02 -0700329 boolean needLayout = false;
330 View widget = getContent();
331 if (widget != null) {
332 LayoutParams lp = (LayoutParams) widget.getLayoutParams();
333 if (lp.height != height) {
334 needLayout = true;
335 lp.height = height;
336 }
337 }
338 if (needLayout) {
339 requestLayout();
340 }
341 }
342
Adam Cohen4ddcd572012-11-01 17:36:32 -0700343 public void setMaxChallengeTop(int top) {
344 boolean dirty = mMaxChallengeTop != top;
Adam Cohen44dc1412012-11-07 20:50:39 -0800345 mMaxChallengeTop = top;
Adam Cohen4ddcd572012-11-01 17:36:32 -0700346 mSmallWidgetHeight = top - getPaddingTop();
347 mSmallFrameHeight = top + getPaddingBottom();
348 if (dirty && mIsSmall) {
349 setWidgetHeight(mSmallWidgetHeight);
350 setFrameHeight(mSmallFrameHeight);
351 } else if (dirty && mWidgetLockedSmall) {
352 setWidgetHeight(mSmallWidgetHeight);
353 }
354 }
355
Adam Cohene3643132012-10-28 18:29:17 -0700356 public boolean isSmall() {
357 return mIsSmall;
358 }
359
360 public void adjustFrame(int challengeTop) {
Adam Cohen4ddcd572012-11-01 17:36:32 -0700361 int frameHeight = challengeTop + getPaddingBottom();
362 setFrameHeight(frameHeight);
Adam Cohene3643132012-10-28 18:29:17 -0700363 }
364
Adam Cohen44dc1412012-11-07 20:50:39 -0800365 public void shrinkWidget(boolean alsoShrinkFrame) {
Adam Cohene3643132012-10-28 18:29:17 -0700366 mIsSmall = true;
Adam Cohen4ddcd572012-11-01 17:36:32 -0700367 setWidgetHeight(mSmallWidgetHeight);
Adam Cohen44dc1412012-11-07 20:50:39 -0800368
369 if (alsoShrinkFrame) {
370 setFrameHeight(mSmallFrameHeight);
371 }
372 }
373
374 public int getSmallFrameHeight() {
375 return mSmallFrameHeight;
376 }
377
Adam Cohen4ddcd572012-11-01 17:36:32 -0700378 public void setWidgetLockedSmall(boolean locked) {
Adam Cohen86006bb2012-11-02 00:13:24 -0700379 if (locked) {
380 setWidgetHeight(mSmallWidgetHeight);
381 }
Adam Cohen4ddcd572012-11-01 17:36:32 -0700382 mWidgetLockedSmall = locked;
Jim Millerd6523da2012-10-21 16:47:02 -0700383 }
384
385 public void resetSize() {
Adam Cohene3643132012-10-28 18:29:17 -0700386 mIsSmall = false;
Adam Cohen4ddcd572012-11-01 17:36:32 -0700387 if (!mWidgetLockedSmall) {
388 setWidgetHeight(LayoutParams.MATCH_PARENT);
389 }
Adam Cohene3643132012-10-28 18:29:17 -0700390 setFrameHeight(getMeasuredHeight());
Jim Millerd6523da2012-10-21 16:47:02 -0700391 }
392
Adam Cohene3643132012-10-28 18:29:17 -0700393 public void setFrameHeight(int height) {
Adam Cohen4ddcd572012-11-01 17:36:32 -0700394 mFrameHeight = height;
395 mBackgroundRect.set(0, 0, getMeasuredWidth(), Math.min(mFrameHeight, getMeasuredHeight()));
Adam Cohend51700b32012-11-07 16:26:46 -0800396 mForegroundRect.set(mFrameStrokeAdjustment, mFrameStrokeAdjustment,getMeasuredWidth() -
397 mFrameStrokeAdjustment, Math.min(getMeasuredHeight(), mFrameHeight) -
398 mFrameStrokeAdjustment);
399 updateGradient();
Adam Cohene3643132012-10-28 18:29:17 -0700400 invalidate();
401 }
402
403 public void hideFrame(Object caller) {
Adam Cohendb1c5d52012-11-03 17:10:07 -0700404 fadeFrame(caller, false, 0f, KeyguardWidgetPager.CHILDREN_OUTLINE_FADE_OUT_DURATION);
Adam Cohene3643132012-10-28 18:29:17 -0700405 }
406
407 public void showFrame(Object caller) {
Adam Cohendb1c5d52012-11-03 17:10:07 -0700408 fadeFrame(caller, true, OUTLINE_ALPHA_MULTIPLIER,
409 KeyguardWidgetPager.CHILDREN_OUTLINE_FADE_IN_DURATION);
Adam Cohene3643132012-10-28 18:29:17 -0700410 }
411
412 public void fadeFrame(Object caller, boolean takeControl, float alpha, int duration) {
413 if (takeControl) {
414 mBgAlphaController = caller;
415 }
416
Adam Cohen2b0501b2012-11-21 16:49:13 -0800417 if (mBgAlphaController != caller && mBgAlphaController != null) {
418 return;
419 }
Adam Cohene3643132012-10-28 18:29:17 -0700420
421 if (mFrameFade != null) {
422 mFrameFade.cancel();
423 mFrameFade = null;
424 }
425 PropertyValuesHolder bgAlpha = PropertyValuesHolder.ofFloat("backgroundAlpha", alpha);
426 mFrameFade = ObjectAnimator.ofPropertyValuesHolder(this, bgAlpha);
427 mFrameFade.setDuration(duration);
428 mFrameFade.start();
429 }
430
Adam Cohend51700b32012-11-07 16:26:46 -0800431 private void updateGradient() {
Adam Cohen61cd69c2012-10-02 21:42:54 -0700432 float x0 = mLeftToRight ? 0 : mForegroundRect.width();
433 float x1 = mLeftToRight ? mForegroundRect.width(): 0;
434 mLeftToRightGradient = new LinearGradient(x0, 0f, x1, 0f,
435 mGradientColor, 0, Shader.TileMode.CLAMP);
436 mRightToLeftGradient = new LinearGradient(x1, 0f, x0, 0f,
437 mGradientColor, 0, Shader.TileMode.CLAMP);
Adam Cohend51700b32012-11-07 16:26:46 -0800438 }
439
440 @Override
441 protected void onSizeChanged(int w, int h, int oldw, int oldh) {
442 super.onSizeChanged(w, h, oldw, oldh);
Adam Cohen4ddcd572012-11-01 17:36:32 -0700443
444 if (!mIsSmall) {
445 mFrameHeight = h;
446 }
447
Adam Cohend51700b32012-11-07 16:26:46 -0800448 // mFrameStrokeAdjustment is a cludge to prevent the overlay from drawing outside the
449 // rounded rect background.
450 mForegroundRect.set(mFrameStrokeAdjustment, mFrameStrokeAdjustment,
451 w - mFrameStrokeAdjustment, Math.min(h, mFrameHeight) - mFrameStrokeAdjustment);
452
Adam Cohen4ddcd572012-11-01 17:36:32 -0700453 mBackgroundRect.set(0, 0, getMeasuredWidth(), Math.min(h, mFrameHeight));
Adam Cohend51700b32012-11-07 16:26:46 -0800454 updateGradient();
Adam Cohene3643132012-10-28 18:29:17 -0700455 invalidate();
Jim Millerf2dfc352012-08-29 18:42:21 -0700456 }
457
Adam Cohen4ddcd572012-11-01 17:36:32 -0700458 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
459 super.onMeasure(widthMeasureSpec, heightMeasureSpec);
460 performAppWidgetSizeCallbacksIfNecessary();
461 }
462
463 private void performAppWidgetSizeCallbacksIfNecessary() {
464 View content = getContent();
465 if (!(content instanceof AppWidgetHostView)) return;
466
Adam Cohenc276e822012-11-08 13:01:08 -0800467 if (!KeyguardUpdateMonitor.getInstance(mContext).hasBootCompleted()) {
468 mPerformAppWidgetSizeUpdateOnBootComplete = true;
469 return;
Adam Cohen4ddcd572012-11-01 17:36:32 -0700470 }
471
Adam Cohenc276e822012-11-08 13:01:08 -0800472 // TODO: there's no reason to force the AppWidgetHostView to catch duplicate size calls.
473 // We can do that even more cheaply here. It's not an issue right now since we're in the
474 // system process and hence no binder calls.
Adam Cohen4ddcd572012-11-01 17:36:32 -0700475 AppWidgetHostView awhv = (AppWidgetHostView) content;
476 float density = getResources().getDisplayMetrics().density;
477
478 int width = (int) (content.getMeasuredWidth() / density);
479 int height = (int) (content.getMeasuredHeight() / density);
480 awhv.updateAppWidgetSize(null, width, height, width, height, true);
481 }
482
Jim Millerf2dfc352012-08-29 18:42:21 -0700483 void setOverScrollAmount(float r, boolean left) {
Adam Cohen66b9fb1662012-09-05 16:23:58 -0700484 if (Float.compare(mOverScrollAmount, r) != 0) {
485 mOverScrollAmount = r;
Adam Cohen61cd69c2012-10-02 21:42:54 -0700486 mForegroundGradient = left ? mLeftToRightGradient : mRightToLeftGradient;
Adam Cohen5d47a8d2012-11-03 19:10:56 -0700487 mForegroundAlpha = (int) Math.round((0.5f * r * 255));
488
489 // We bump up the alpha of the outline to hide the fact that the overlay is drawing
490 // over the rounded part of the frame.
Adam Cohen934d0832012-11-03 20:02:33 -0700491 float bgAlpha = Math.min(OUTLINE_ALPHA_MULTIPLIER + r * (1 - OUTLINE_ALPHA_MULTIPLIER),
492 1f);
493 setBackgroundAlpha(bgAlpha);
Adam Cohen66b9fb1662012-09-05 16:23:58 -0700494 invalidate();
495 }
Jim Millerf2dfc352012-08-29 18:42:21 -0700496 }
John Spurlock86b63572012-10-24 11:24:25 -0400497
498 public void onActive(boolean isActive) {
499 // hook for subclasses
500 }
John Spurlock4b976ea2012-10-28 12:34:11 -0400501
John Spurlockbb5c9412012-10-31 09:46:15 -0400502 public boolean onUserInteraction(MotionEvent event) {
John Spurlock4b976ea2012-10-28 12:34:11 -0400503 // hook for subclasses
504 return false;
505 }
John Spurlock37d84ae2012-11-04 11:11:47 -0500506
John Spurlock0552c5d2012-11-15 08:04:45 -0500507 public void onBouncerShowing(boolean showing) {
508 // hook for subclasses
509 }
510
John Spurlock37d84ae2012-11-04 11:11:47 -0500511 public void setWorkerHandler(Handler workerHandler) {
512 mWorkerHandler = workerHandler;
513 }
514
515 public Handler getWorkerHandler() {
516 return mWorkerHandler;
517 }
John Spurlock0552c5d2012-11-15 08:04:45 -0500518
Jim Millerf2dfc352012-08-29 18:42:21 -0700519}