131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project/* 231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * 431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * you may not use this file except in compliance with the License. 631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * You may obtain a copy of the License at 731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * 831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * 1031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 1131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 1231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * See the License for the specific language governing permissions and 1431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * limitations under the License. 1531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */ 1631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 17a5902524d4403885eb4c50360bf3465c6be796efJoe Onoratopackage com.android.launcher2; 1831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 1931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.content.Context; 20656d11c882296d732e6bdab30ec26f84b99eba19Winson Chungimport android.content.res.Resources; 2167b2f6cba5aa7b5d0fac5e66ba8f3d5f887baee6Michael Jurkaimport android.graphics.Bitmap; 2231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.graphics.Canvas; 2338b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurkaimport android.graphics.Rect; 24137142e39bd65429b0ad3e502aa9851ba81ca6ffMichael Jurkaimport android.graphics.Region; 2538b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurkaimport android.graphics.Region.Op; 2631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.graphics.drawable.Drawable; 27656d11c882296d732e6bdab30ec26f84b99eba19Winson Chungimport android.util.AttributeSet; 2838b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurkaimport android.view.MotionEvent; 29bdb5c5342adc550559fd723af461e53248f2fba8Michael Jurkaimport android.widget.TextView; 30edcce099c98a6c40d10109ac092ab50f9d2668f3Romain Guy 3131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project/** 3231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * TextView that draws a bubble behind the text. We cannot use a LineBackgroundSpan 3331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * because we want to make the bubble taller than the text and TextView's clip is 3431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * too aggressive. 3531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */ 3608ee77090f1fef565142e9341914369b1aa342d1Michael Jurkapublic class BubbleTextView extends TextView { 37656d11c882296d732e6bdab30ec26f84b99eba19Winson Chung static final float CORNER_RADIUS = 4.0f; 3888127038178b3bbf0eb91103a31e682cc0615074Winson Chung static final float SHADOW_LARGE_RADIUS = 4.0f; 3988127038178b3bbf0eb91103a31e682cc0615074Winson Chung static final float SHADOW_SMALL_RADIUS = 1.75f; 4088127038178b3bbf0eb91103a31e682cc0615074Winson Chung static final float SHADOW_Y_OFFSET = 2.0f; 41c7aef8ca7593eaa37ac7dde514e139f113399ce7Winson Chung static final int SHADOW_LARGE_COLOUR = 0xDD000000; 42c7aef8ca7593eaa37ac7dde514e139f113399ce7Winson Chung static final int SHADOW_SMALL_COLOUR = 0xCC000000; 43656d11c882296d732e6bdab30ec26f84b99eba19Winson Chung static final float PADDING_H = 8.0f; 44656d11c882296d732e6bdab30ec26f84b99eba19Winson Chung static final float PADDING_V = 3.0f; 45656d11c882296d732e6bdab30ec26f84b99eba19Winson Chung 46e22a8e9d3eafe569fe0f4d284c77af08c6e2fe28Winson Chung private int mPrevAlpha = -1; 4731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 4838b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka private final HolographicOutlineHelper mOutlineHelper = new HolographicOutlineHelper(); 4938b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka private final Canvas mTempCanvas = new Canvas(); 5038b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka private final Rect mTempRect = new Rect(); 5138b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka private boolean mDidInvalidateForPressedState; 5238b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka private Bitmap mPressedOrFocusedBackground; 5338b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka private int mFocusedOutlineColor; 5438b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka private int mFocusedGlowColor; 5538b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka private int mPressedOutlineColor; 5638b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka private int mPressedGlowColor; 5738b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka 5831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project private boolean mBackgroundSizeChanged; 5931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project private Drawable mBackground; 6031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 61ddd62e9f3dd21c52dffceef9b168629ebb7f4c03Michael Jurka private boolean mStayPressed; 6288f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung private CheckLongPressHelper mLongPressHelper; 63ddd62e9f3dd21c52dffceef9b168629ebb7f4c03Michael Jurka 6431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project public BubbleTextView(Context context) { 6531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project super(context); 6631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project init(); 6731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 6831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 6931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project public BubbleTextView(Context context, AttributeSet attrs) { 7031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project super(context, attrs); 7131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project init(); 7231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 7331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 7431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project public BubbleTextView(Context context, AttributeSet attrs, int defStyle) { 7531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project super(context, attrs, defStyle); 7631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project init(); 7731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 7831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 7931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project private void init() { 8088f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung mLongPressHelper = new CheckLongPressHelper(this); 8131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project mBackground = getBackground(); 8231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 83656d11c882296d732e6bdab30ec26f84b99eba19Winson Chung final Resources res = getContext().getResources(); 847d3810d8337e4f030796b566a2d562fcf79b0a22Winson Chung mFocusedOutlineColor = mFocusedGlowColor = mPressedOutlineColor = mPressedGlowColor = 8552ee3ec0beb56a37575aa37c6788823102c3bd6dMichael Feldstein res.getColor(android.R.color.white); 86e7e3f6c438a9de1d4a0557962f868d9a01f56286Michael Jurka 87e7e3f6c438a9de1d4a0557962f868d9a01f56286Michael Jurka setShadowLayer(SHADOW_LARGE_RADIUS, 0.0f, SHADOW_Y_OFFSET, SHADOW_LARGE_COLOUR); 8831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 8931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 9067b2f6cba5aa7b5d0fac5e66ba8f3d5f887baee6Michael Jurka public void applyFromShortcutInfo(ShortcutInfo info, IconCache iconCache) { 9167b2f6cba5aa7b5d0fac5e66ba8f3d5f887baee6Michael Jurka Bitmap b = info.getIcon(iconCache); 9267b2f6cba5aa7b5d0fac5e66ba8f3d5f887baee6Michael Jurka 9367b2f6cba5aa7b5d0fac5e66ba8f3d5f887baee6Michael Jurka setCompoundDrawablesWithIntrinsicBounds(null, 9467b2f6cba5aa7b5d0fac5e66ba8f3d5f887baee6Michael Jurka new FastBitmapDrawable(b), 9567b2f6cba5aa7b5d0fac5e66ba8f3d5f887baee6Michael Jurka null, null); 9667b2f6cba5aa7b5d0fac5e66ba8f3d5f887baee6Michael Jurka setText(info.title); 974d3aca0989c48084c0c387d6010bd5b601c25668Kenny Guy if (info.contentDescription != null) { 984d3aca0989c48084c0c387d6010bd5b601c25668Kenny Guy setContentDescription(info.contentDescription); 994d3aca0989c48084c0c387d6010bd5b601c25668Kenny Guy } 10067b2f6cba5aa7b5d0fac5e66ba8f3d5f887baee6Michael Jurka setTag(info); 10167b2f6cba5aa7b5d0fac5e66ba8f3d5f887baee6Michael Jurka } 10267b2f6cba5aa7b5d0fac5e66ba8f3d5f887baee6Michael Jurka 10331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project @Override 10431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project protected boolean setFrame(int left, int top, int right, int bottom) { 1058b805b17158886035b38261eb611d8641701ae43Michael Jurka if (getLeft() != left || getRight() != right || getTop() != top || getBottom() != bottom) { 10631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project mBackgroundSizeChanged = true; 10731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 10831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project return super.setFrame(left, top, right, bottom); 10931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 11031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 11131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project @Override 11231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project protected boolean verifyDrawable(Drawable who) { 11331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project return who == mBackground || super.verifyDrawable(who); 11431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 11531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 11631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project @Override 117816474f06b9bea400f4511fa35b63a7f18a54c54Michael Jurka public void setTag(Object tag) { 118816474f06b9bea400f4511fa35b63a7f18a54c54Michael Jurka if (tag != null) { 119816474f06b9bea400f4511fa35b63a7f18a54c54Michael Jurka LauncherModel.checkItemInfo((ItemInfo) tag); 120816474f06b9bea400f4511fa35b63a7f18a54c54Michael Jurka } 121816474f06b9bea400f4511fa35b63a7f18a54c54Michael Jurka super.setTag(tag); 122816474f06b9bea400f4511fa35b63a7f18a54c54Michael Jurka } 123816474f06b9bea400f4511fa35b63a7f18a54c54Michael Jurka 124816474f06b9bea400f4511fa35b63a7f18a54c54Michael Jurka @Override 12531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project protected void drawableStateChanged() { 12638b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka if (isPressed()) { 12738b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka // In this case, we have already created the pressed outline on ACTION_DOWN, 12838b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka // so we just need to do an invalidate to trigger draw 12938b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka if (!mDidInvalidateForPressedState) { 1303499d8c89d6b5989579880bf80df31df46483304Patrick Dubroy setCellLayoutPressedOrFocusedIcon(); 13138b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka } 13238b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka } else { 13338b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka // Otherwise, either clear the pressed/focused background, or create a background 13438b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka // for the focused state 13538b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka final boolean backgroundEmptyBefore = mPressedOrFocusedBackground == null; 136ddd62e9f3dd21c52dffceef9b168629ebb7f4c03Michael Jurka if (!mStayPressed) { 137ddd62e9f3dd21c52dffceef9b168629ebb7f4c03Michael Jurka mPressedOrFocusedBackground = null; 138ddd62e9f3dd21c52dffceef9b168629ebb7f4c03Michael Jurka } 13938b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka if (isFocused()) { 140c786952c9d2277a3cf631ab425dcfaf6dee6a9eaGilles Debunne if (getLayout() == null) { 141a017c0379c30e0272a88a93d05b6a30e28955b88Patrick Dubroy // In some cases, we get focus before we have been layed out. Set the 142a017c0379c30e0272a88a93d05b6a30e28955b88Patrick Dubroy // background to null so that it will get created when the view is drawn. 143a017c0379c30e0272a88a93d05b6a30e28955b88Patrick Dubroy mPressedOrFocusedBackground = null; 144a017c0379c30e0272a88a93d05b6a30e28955b88Patrick Dubroy } else { 145a017c0379c30e0272a88a93d05b6a30e28955b88Patrick Dubroy mPressedOrFocusedBackground = createGlowingOutline( 146a017c0379c30e0272a88a93d05b6a30e28955b88Patrick Dubroy mTempCanvas, mFocusedGlowColor, mFocusedOutlineColor); 147a017c0379c30e0272a88a93d05b6a30e28955b88Patrick Dubroy } 148ddd62e9f3dd21c52dffceef9b168629ebb7f4c03Michael Jurka mStayPressed = false; 1493499d8c89d6b5989579880bf80df31df46483304Patrick Dubroy setCellLayoutPressedOrFocusedIcon(); 15038b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka } 15138b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka final boolean backgroundEmptyNow = mPressedOrFocusedBackground == null; 15238b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka if (!backgroundEmptyBefore && backgroundEmptyNow) { 1533499d8c89d6b5989579880bf80df31df46483304Patrick Dubroy setCellLayoutPressedOrFocusedIcon(); 15438b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka } 15538b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka } 15638b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka 15731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project Drawable d = mBackground; 15831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project if (d != null && d.isStateful()) { 15931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project d.setState(getDrawableState()); 16031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 16131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project super.drawableStateChanged(); 16231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 16331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 16438b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka /** 165cd953711fcbb6c8c6579fb7127e3c86103c0d409Patrick Dubroy * Draw this BubbleTextView into the given Canvas. 16638b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka * 16738b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka * @param destCanvas the canvas to draw on 16838b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka * @param padding the horizontal and vertical padding to use when drawing 16938b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka */ 17038b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka private void drawWithPadding(Canvas destCanvas, int padding) { 17138b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka final Rect clipRect = mTempRect; 17238b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka getDrawingRect(clipRect); 17338b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka 17438b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka // adjust the clip rect so that we don't include the text label 17538b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka clipRect.bottom = 17638b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka getExtendedPaddingTop() - (int) BubbleTextView.PADDING_V + getLayout().getLineTop(0); 17738b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka 17838b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka // Draw the View into the bitmap. 17938b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka // The translate of scrollX and scrollY is necessary when drawing TextViews, because 18038b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka // they set scrollX and scrollY to large values to achieve centered text 18138b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka destCanvas.save(); 182eecf02da58adef5486bf0c9ff7127ea891f457a4Winson Chung destCanvas.scale(getScaleX(), getScaleY(), 183eecf02da58adef5486bf0c9ff7127ea891f457a4Winson Chung (getWidth() + padding) / 2, (getHeight() + padding) / 2); 18438b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka destCanvas.translate(-getScrollX() + padding / 2, -getScrollY() + padding / 2); 18538b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka destCanvas.clipRect(clipRect, Op.REPLACE); 1863499d8c89d6b5989579880bf80df31df46483304Patrick Dubroy draw(destCanvas); 18738b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka destCanvas.restore(); 18838b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka } 18938b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka 19038b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka /** 19138b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka * Returns a new bitmap to be used as the object outline, e.g. to visualize the drop location. 19238b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka * Responsibility for the bitmap is transferred to the caller. 19338b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka */ 19438b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka private Bitmap createGlowingOutline(Canvas canvas, int outlineColor, int glowColor) { 19538b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka final int padding = HolographicOutlineHelper.MAX_OUTER_BLUR_RADIUS; 19638b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka final Bitmap b = Bitmap.createBitmap( 19738b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka getWidth() + padding, getHeight() + padding, Bitmap.Config.ARGB_8888); 19838b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka 19938b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka canvas.setBitmap(b); 20038b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka drawWithPadding(canvas, padding); 20138b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka mOutlineHelper.applyExtraThickExpensiveOutlineWithBlur(b, canvas, glowColor, outlineColor); 202aaf473c2bb6329b3b09ed2e19de6aae26077050cAdam Cohen canvas.setBitmap(null); 20338b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka 20438b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka return b; 20538b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka } 20638b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka 20738b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka @Override 20838b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka public boolean onTouchEvent(MotionEvent event) { 20938b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka // Call the superclass onTouchEvent first, because sometimes it changes the state to 21038b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka // isPressed() on an ACTION_UP 21138b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka boolean result = super.onTouchEvent(event); 21238b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka 21338b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka switch (event.getAction()) { 21438b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka case MotionEvent.ACTION_DOWN: 21538b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka // So that the pressed outline is visible immediately when isPressed() is true, 21638b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka // we pre-create it on ACTION_DOWN (it takes a small but perceptible amount of time 21738b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka // to create it) 21838b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka if (mPressedOrFocusedBackground == null) { 21938b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka mPressedOrFocusedBackground = createGlowingOutline( 22038b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka mTempCanvas, mPressedGlowColor, mPressedOutlineColor); 22138b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka } 22238b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka // Invalidate so the pressed state is visible, or set a flag so we know that we 22338b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka // have to call invalidate as soon as the state is "pressed" 22438b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka if (isPressed()) { 22538b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka mDidInvalidateForPressedState = true; 226e6235dd225404239b55c459245543f3302326112Michael Jurka setCellLayoutPressedOrFocusedIcon(); 22738b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka } else { 22838b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka mDidInvalidateForPressedState = false; 22938b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka } 23088f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung 23188f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung mLongPressHelper.postCheckForLongPress(); 23238b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka break; 23338b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka case MotionEvent.ACTION_CANCEL: 23438b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka case MotionEvent.ACTION_UP: 23538b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka // If we've touched down and up on an item, and it's still not "pressed", then 23638b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka // destroy the pressed outline 23738b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka if (!isPressed()) { 23838b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka mPressedOrFocusedBackground = null; 23938b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka } 24088f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung 24188f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung mLongPressHelper.cancelLongPress(); 24238b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka break; 24338b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka } 24438b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka return result; 24538b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka } 24638b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka 247ddd62e9f3dd21c52dffceef9b168629ebb7f4c03Michael Jurka void setStayPressed(boolean stayPressed) { 248ddd62e9f3dd21c52dffceef9b168629ebb7f4c03Michael Jurka mStayPressed = stayPressed; 249ddd62e9f3dd21c52dffceef9b168629ebb7f4c03Michael Jurka if (!stayPressed) { 250ddd62e9f3dd21c52dffceef9b168629ebb7f4c03Michael Jurka mPressedOrFocusedBackground = null; 251ddd62e9f3dd21c52dffceef9b168629ebb7f4c03Michael Jurka } 2523499d8c89d6b5989579880bf80df31df46483304Patrick Dubroy setCellLayoutPressedOrFocusedIcon(); 253ddd62e9f3dd21c52dffceef9b168629ebb7f4c03Michael Jurka } 254a017c0379c30e0272a88a93d05b6a30e28955b88Patrick Dubroy 2553499d8c89d6b5989579880bf80df31df46483304Patrick Dubroy void setCellLayoutPressedOrFocusedIcon() { 256a52570f8f9ad65b85e33a2f2e87722f9edd6c6f4Michael Jurka if (getParent() instanceof ShortcutAndWidgetContainer) { 257a52570f8f9ad65b85e33a2f2e87722f9edd6c6f4Michael Jurka ShortcutAndWidgetContainer parent = (ShortcutAndWidgetContainer) getParent(); 25876fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen if (parent != null) { 25976fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen CellLayout layout = (CellLayout) parent.getParent(); 26076fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen layout.setPressedOrFocusedIcon((mPressedOrFocusedBackground != null) ? this : null); 26176fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen } 262d69e11384c9eefe49039b198edcece5d59c8868fPatrick Dubroy } 263a017c0379c30e0272a88a93d05b6a30e28955b88Patrick Dubroy } 264a017c0379c30e0272a88a93d05b6a30e28955b88Patrick Dubroy 2651e9cbfef04366a206d59922c14fe4356b7cca426Winson Chung void clearPressedOrFocusedBackground() { 2661e9cbfef04366a206d59922c14fe4356b7cca426Winson Chung mPressedOrFocusedBackground = null; 2671e9cbfef04366a206d59922c14fe4356b7cca426Winson Chung setCellLayoutPressedOrFocusedIcon(); 2681e9cbfef04366a206d59922c14fe4356b7cca426Winson Chung } 2691e9cbfef04366a206d59922c14fe4356b7cca426Winson Chung 2703499d8c89d6b5989579880bf80df31df46483304Patrick Dubroy Bitmap getPressedOrFocusedBackground() { 2713499d8c89d6b5989579880bf80df31df46483304Patrick Dubroy return mPressedOrFocusedBackground; 2723499d8c89d6b5989579880bf80df31df46483304Patrick Dubroy } 273a017c0379c30e0272a88a93d05b6a30e28955b88Patrick Dubroy 2743499d8c89d6b5989579880bf80df31df46483304Patrick Dubroy int getPressedOrFocusedBackgroundPadding() { 2753499d8c89d6b5989579880bf80df31df46483304Patrick Dubroy return HolographicOutlineHelper.MAX_OUTER_BLUR_RADIUS / 2; 2763499d8c89d6b5989579880bf80df31df46483304Patrick Dubroy } 27788127038178b3bbf0eb91103a31e682cc0615074Winson Chung 2783499d8c89d6b5989579880bf80df31df46483304Patrick Dubroy @Override 2793499d8c89d6b5989579880bf80df31df46483304Patrick Dubroy public void draw(Canvas canvas) { 280bdb5c5342adc550559fd723af461e53248f2fba8Michael Jurka final Drawable background = mBackground; 281bdb5c5342adc550559fd723af461e53248f2fba8Michael Jurka if (background != null) { 2828b805b17158886035b38261eb611d8641701ae43Michael Jurka final int scrollX = getScrollX(); 2838b805b17158886035b38261eb611d8641701ae43Michael Jurka final int scrollY = getScrollY(); 284bdb5c5342adc550559fd723af461e53248f2fba8Michael Jurka 285bdb5c5342adc550559fd723af461e53248f2fba8Michael Jurka if (mBackgroundSizeChanged) { 2868b805b17158886035b38261eb611d8641701ae43Michael Jurka background.setBounds(0, 0, getRight() - getLeft(), getBottom() - getTop()); 287bdb5c5342adc550559fd723af461e53248f2fba8Michael Jurka mBackgroundSizeChanged = false; 288bdb5c5342adc550559fd723af461e53248f2fba8Michael Jurka } 289bdb5c5342adc550559fd723af461e53248f2fba8Michael Jurka 290bdb5c5342adc550559fd723af461e53248f2fba8Michael Jurka if ((scrollX | scrollY) == 0) { 291bdb5c5342adc550559fd723af461e53248f2fba8Michael Jurka background.draw(canvas); 292bdb5c5342adc550559fd723af461e53248f2fba8Michael Jurka } else { 293bdb5c5342adc550559fd723af461e53248f2fba8Michael Jurka canvas.translate(scrollX, scrollY); 294bdb5c5342adc550559fd723af461e53248f2fba8Michael Jurka background.draw(canvas); 295bdb5c5342adc550559fd723af461e53248f2fba8Michael Jurka canvas.translate(-scrollX, -scrollY); 29631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 29707f2e81d77b5f788e1d812011ea3d5b74acde4e4Winson Chung } 2980dca1ec41479a74f8da080224fa0c7eacab674d6Andrew Flynn 2990dca1ec41479a74f8da080224fa0c7eacab674d6Andrew Flynn // If text is transparent, don't draw any shadow 300bc239a15464f543a41b960b946aa77258454efafAndrew Flynn if (getCurrentTextColor() == getResources().getColor(android.R.color.transparent)) { 3010dca1ec41479a74f8da080224fa0c7eacab674d6Andrew Flynn getPaint().clearShadowLayer(); 3020dca1ec41479a74f8da080224fa0c7eacab674d6Andrew Flynn super.draw(canvas); 3030dca1ec41479a74f8da080224fa0c7eacab674d6Andrew Flynn return; 3040dca1ec41479a74f8da080224fa0c7eacab674d6Andrew Flynn } 3050dca1ec41479a74f8da080224fa0c7eacab674d6Andrew Flynn 306bdb5c5342adc550559fd723af461e53248f2fba8Michael Jurka // We enhance the shadow by drawing the shadow twice 307e7e3f6c438a9de1d4a0557962f868d9a01f56286Michael Jurka getPaint().setShadowLayer(SHADOW_LARGE_RADIUS, 0.0f, SHADOW_Y_OFFSET, SHADOW_LARGE_COLOUR); 308bdb5c5342adc550559fd723af461e53248f2fba8Michael Jurka super.draw(canvas); 309bdb5c5342adc550559fd723af461e53248f2fba8Michael Jurka canvas.save(Canvas.CLIP_SAVE_FLAG); 3108b805b17158886035b38261eb611d8641701ae43Michael Jurka canvas.clipRect(getScrollX(), getScrollY() + getExtendedPaddingTop(), 3118b805b17158886035b38261eb611d8641701ae43Michael Jurka getScrollX() + getWidth(), 3128b805b17158886035b38261eb611d8641701ae43Michael Jurka getScrollY() + getHeight(), Region.Op.INTERSECT); 313e7e3f6c438a9de1d4a0557962f868d9a01f56286Michael Jurka getPaint().setShadowLayer(SHADOW_SMALL_RADIUS, 0.0f, 0.0f, SHADOW_SMALL_COLOUR); 314bdb5c5342adc550559fd723af461e53248f2fba8Michael Jurka super.draw(canvas); 315bdb5c5342adc550559fd723af461e53248f2fba8Michael Jurka canvas.restore(); 31631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 3179c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato 3189c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato @Override 3199c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato protected void onAttachedToWindow() { 3209c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato super.onAttachedToWindow(); 321656d11c882296d732e6bdab30ec26f84b99eba19Winson Chung if (mBackground != null) mBackground.setCallback(this); 3229c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato } 3239c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato 3249c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato @Override 3259c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato protected void onDetachedFromWindow() { 3269c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato super.onDetachedFromWindow(); 327656d11c882296d732e6bdab30ec26f84b99eba19Winson Chung if (mBackground != null) mBackground.setCallback(null); 3289c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato } 329affd7b4d23cecb4ed74133dd8bd9a5ede099c562Winson Chung 330affd7b4d23cecb4ed74133dd8bd9a5ede099c562Winson Chung @Override 331affd7b4d23cecb4ed74133dd8bd9a5ede099c562Winson Chung protected boolean onSetAlpha(int alpha) { 332e22a8e9d3eafe569fe0f4d284c77af08c6e2fe28Winson Chung if (mPrevAlpha != alpha) { 333e22a8e9d3eafe569fe0f4d284c77af08c6e2fe28Winson Chung mPrevAlpha = alpha; 334e22a8e9d3eafe569fe0f4d284c77af08c6e2fe28Winson Chung super.onSetAlpha(alpha); 335e22a8e9d3eafe569fe0f4d284c77af08c6e2fe28Winson Chung } 336e22a8e9d3eafe569fe0f4d284c77af08c6e2fe28Winson Chung return true; 337affd7b4d23cecb4ed74133dd8bd9a5ede099c562Winson Chung } 33888f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung 33988f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung @Override 34088f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung public void cancelLongPress() { 34188f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung super.cancelLongPress(); 34288f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung 34388f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung mLongPressHelper.cancelLongPress(); 34488f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung } 34531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project} 346