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 = 857d3810d8337e4f030796b566a2d562fcf79b0a22Winson Chung res.getColor(android.R.color.holo_blue_light); 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); 9767b2f6cba5aa7b5d0fac5e66ba8f3d5f887baee6Michael Jurka setTag(info); 9867b2f6cba5aa7b5d0fac5e66ba8f3d5f887baee6Michael Jurka } 9967b2f6cba5aa7b5d0fac5e66ba8f3d5f887baee6Michael Jurka 10031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project @Override 10131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project protected boolean setFrame(int left, int top, int right, int bottom) { 1028b805b17158886035b38261eb611d8641701ae43Michael Jurka if (getLeft() != left || getRight() != right || getTop() != top || getBottom() != bottom) { 10331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project mBackgroundSizeChanged = true; 10431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 10531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project return super.setFrame(left, top, right, bottom); 10631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 10731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 10831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project @Override 10931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project protected boolean verifyDrawable(Drawable who) { 11031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project return who == mBackground || super.verifyDrawable(who); 11131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 11231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 11331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project @Override 11431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project protected void drawableStateChanged() { 11538b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka if (isPressed()) { 11638b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka // In this case, we have already created the pressed outline on ACTION_DOWN, 11738b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka // so we just need to do an invalidate to trigger draw 11838b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka if (!mDidInvalidateForPressedState) { 1193499d8c89d6b5989579880bf80df31df46483304Patrick Dubroy setCellLayoutPressedOrFocusedIcon(); 12038b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka } 12138b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka } else { 12238b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka // Otherwise, either clear the pressed/focused background, or create a background 12338b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka // for the focused state 12438b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka final boolean backgroundEmptyBefore = mPressedOrFocusedBackground == null; 125ddd62e9f3dd21c52dffceef9b168629ebb7f4c03Michael Jurka if (!mStayPressed) { 126ddd62e9f3dd21c52dffceef9b168629ebb7f4c03Michael Jurka mPressedOrFocusedBackground = null; 127ddd62e9f3dd21c52dffceef9b168629ebb7f4c03Michael Jurka } 12838b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka if (isFocused()) { 129c786952c9d2277a3cf631ab425dcfaf6dee6a9eaGilles Debunne if (getLayout() == null) { 130a017c0379c30e0272a88a93d05b6a30e28955b88Patrick Dubroy // In some cases, we get focus before we have been layed out. Set the 131a017c0379c30e0272a88a93d05b6a30e28955b88Patrick Dubroy // background to null so that it will get created when the view is drawn. 132a017c0379c30e0272a88a93d05b6a30e28955b88Patrick Dubroy mPressedOrFocusedBackground = null; 133a017c0379c30e0272a88a93d05b6a30e28955b88Patrick Dubroy } else { 134a017c0379c30e0272a88a93d05b6a30e28955b88Patrick Dubroy mPressedOrFocusedBackground = createGlowingOutline( 135a017c0379c30e0272a88a93d05b6a30e28955b88Patrick Dubroy mTempCanvas, mFocusedGlowColor, mFocusedOutlineColor); 136a017c0379c30e0272a88a93d05b6a30e28955b88Patrick Dubroy } 137ddd62e9f3dd21c52dffceef9b168629ebb7f4c03Michael Jurka mStayPressed = false; 1383499d8c89d6b5989579880bf80df31df46483304Patrick Dubroy setCellLayoutPressedOrFocusedIcon(); 13938b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka } 14038b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka final boolean backgroundEmptyNow = mPressedOrFocusedBackground == null; 14138b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka if (!backgroundEmptyBefore && backgroundEmptyNow) { 1423499d8c89d6b5989579880bf80df31df46483304Patrick Dubroy setCellLayoutPressedOrFocusedIcon(); 14338b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka } 14438b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka } 14538b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka 14631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project Drawable d = mBackground; 14731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project if (d != null && d.isStateful()) { 14831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project d.setState(getDrawableState()); 14931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 15031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project super.drawableStateChanged(); 15131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 15231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 15338b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka /** 154cd953711fcbb6c8c6579fb7127e3c86103c0d409Patrick Dubroy * Draw this BubbleTextView into the given Canvas. 15538b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka * 15638b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka * @param destCanvas the canvas to draw on 15738b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka * @param padding the horizontal and vertical padding to use when drawing 15838b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka */ 15938b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka private void drawWithPadding(Canvas destCanvas, int padding) { 16038b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka final Rect clipRect = mTempRect; 16138b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka getDrawingRect(clipRect); 16238b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka 16338b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka // adjust the clip rect so that we don't include the text label 16438b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka clipRect.bottom = 16538b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka getExtendedPaddingTop() - (int) BubbleTextView.PADDING_V + getLayout().getLineTop(0); 16638b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka 16738b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka // Draw the View into the bitmap. 16838b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka // The translate of scrollX and scrollY is necessary when drawing TextViews, because 16938b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka // they set scrollX and scrollY to large values to achieve centered text 17038b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka destCanvas.save(); 171eecf02da58adef5486bf0c9ff7127ea891f457a4Winson Chung destCanvas.scale(getScaleX(), getScaleY(), 172eecf02da58adef5486bf0c9ff7127ea891f457a4Winson Chung (getWidth() + padding) / 2, (getHeight() + padding) / 2); 17338b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka destCanvas.translate(-getScrollX() + padding / 2, -getScrollY() + padding / 2); 17438b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka destCanvas.clipRect(clipRect, Op.REPLACE); 1753499d8c89d6b5989579880bf80df31df46483304Patrick Dubroy draw(destCanvas); 17638b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka destCanvas.restore(); 17738b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka } 17838b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka 17938b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka /** 18038b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka * Returns a new bitmap to be used as the object outline, e.g. to visualize the drop location. 18138b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka * Responsibility for the bitmap is transferred to the caller. 18238b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka */ 18338b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka private Bitmap createGlowingOutline(Canvas canvas, int outlineColor, int glowColor) { 18438b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka final int padding = HolographicOutlineHelper.MAX_OUTER_BLUR_RADIUS; 18538b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka final Bitmap b = Bitmap.createBitmap( 18638b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka getWidth() + padding, getHeight() + padding, Bitmap.Config.ARGB_8888); 18738b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka 18838b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka canvas.setBitmap(b); 18938b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka drawWithPadding(canvas, padding); 19038b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka mOutlineHelper.applyExtraThickExpensiveOutlineWithBlur(b, canvas, glowColor, outlineColor); 191aaf473c2bb6329b3b09ed2e19de6aae26077050cAdam Cohen canvas.setBitmap(null); 19238b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka 19338b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka return b; 19438b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka } 19538b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka 19638b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka @Override 19738b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka public boolean onTouchEvent(MotionEvent event) { 19838b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka // Call the superclass onTouchEvent first, because sometimes it changes the state to 19938b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka // isPressed() on an ACTION_UP 20038b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka boolean result = super.onTouchEvent(event); 20138b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka 20238b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka switch (event.getAction()) { 20338b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka case MotionEvent.ACTION_DOWN: 20438b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka // So that the pressed outline is visible immediately when isPressed() is true, 20538b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka // we pre-create it on ACTION_DOWN (it takes a small but perceptible amount of time 20638b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka // to create it) 20738b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka if (mPressedOrFocusedBackground == null) { 20838b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka mPressedOrFocusedBackground = createGlowingOutline( 20938b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka mTempCanvas, mPressedGlowColor, mPressedOutlineColor); 21038b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka } 21138b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka // Invalidate so the pressed state is visible, or set a flag so we know that we 21238b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka // have to call invalidate as soon as the state is "pressed" 21338b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka if (isPressed()) { 21438b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka mDidInvalidateForPressedState = true; 215e6235dd225404239b55c459245543f3302326112Michael Jurka setCellLayoutPressedOrFocusedIcon(); 21638b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka } else { 21738b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka mDidInvalidateForPressedState = false; 21838b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka } 21988f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung 22088f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung mLongPressHelper.postCheckForLongPress(); 22138b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka break; 22238b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka case MotionEvent.ACTION_CANCEL: 22338b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka case MotionEvent.ACTION_UP: 22438b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka // If we've touched down and up on an item, and it's still not "pressed", then 22538b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka // destroy the pressed outline 22638b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka if (!isPressed()) { 22738b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka mPressedOrFocusedBackground = null; 22838b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka } 22988f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung 23088f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung mLongPressHelper.cancelLongPress(); 23138b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka break; 23238b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka } 23338b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka return result; 23438b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka } 23538b4f7c5eab773ad36048b5ab8713750dcaaf748Michael Jurka 236ddd62e9f3dd21c52dffceef9b168629ebb7f4c03Michael Jurka void setStayPressed(boolean stayPressed) { 237ddd62e9f3dd21c52dffceef9b168629ebb7f4c03Michael Jurka mStayPressed = stayPressed; 238ddd62e9f3dd21c52dffceef9b168629ebb7f4c03Michael Jurka if (!stayPressed) { 239ddd62e9f3dd21c52dffceef9b168629ebb7f4c03Michael Jurka mPressedOrFocusedBackground = null; 240ddd62e9f3dd21c52dffceef9b168629ebb7f4c03Michael Jurka } 2413499d8c89d6b5989579880bf80df31df46483304Patrick Dubroy setCellLayoutPressedOrFocusedIcon(); 242ddd62e9f3dd21c52dffceef9b168629ebb7f4c03Michael Jurka } 243a017c0379c30e0272a88a93d05b6a30e28955b88Patrick Dubroy 2443499d8c89d6b5989579880bf80df31df46483304Patrick Dubroy void setCellLayoutPressedOrFocusedIcon() { 245a52570f8f9ad65b85e33a2f2e87722f9edd6c6f4Michael Jurka if (getParent() instanceof ShortcutAndWidgetContainer) { 246a52570f8f9ad65b85e33a2f2e87722f9edd6c6f4Michael Jurka ShortcutAndWidgetContainer parent = (ShortcutAndWidgetContainer) getParent(); 24776fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen if (parent != null) { 24876fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen CellLayout layout = (CellLayout) parent.getParent(); 24976fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen layout.setPressedOrFocusedIcon((mPressedOrFocusedBackground != null) ? this : null); 25076fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen } 251d69e11384c9eefe49039b198edcece5d59c8868fPatrick Dubroy } 252a017c0379c30e0272a88a93d05b6a30e28955b88Patrick Dubroy } 253a017c0379c30e0272a88a93d05b6a30e28955b88Patrick Dubroy 2541e9cbfef04366a206d59922c14fe4356b7cca426Winson Chung void clearPressedOrFocusedBackground() { 2551e9cbfef04366a206d59922c14fe4356b7cca426Winson Chung mPressedOrFocusedBackground = null; 2561e9cbfef04366a206d59922c14fe4356b7cca426Winson Chung setCellLayoutPressedOrFocusedIcon(); 2571e9cbfef04366a206d59922c14fe4356b7cca426Winson Chung } 2581e9cbfef04366a206d59922c14fe4356b7cca426Winson Chung 2593499d8c89d6b5989579880bf80df31df46483304Patrick Dubroy Bitmap getPressedOrFocusedBackground() { 2603499d8c89d6b5989579880bf80df31df46483304Patrick Dubroy return mPressedOrFocusedBackground; 2613499d8c89d6b5989579880bf80df31df46483304Patrick Dubroy } 262a017c0379c30e0272a88a93d05b6a30e28955b88Patrick Dubroy 2633499d8c89d6b5989579880bf80df31df46483304Patrick Dubroy int getPressedOrFocusedBackgroundPadding() { 2643499d8c89d6b5989579880bf80df31df46483304Patrick Dubroy return HolographicOutlineHelper.MAX_OUTER_BLUR_RADIUS / 2; 2653499d8c89d6b5989579880bf80df31df46483304Patrick Dubroy } 26688127038178b3bbf0eb91103a31e682cc0615074Winson Chung 2673499d8c89d6b5989579880bf80df31df46483304Patrick Dubroy @Override 2683499d8c89d6b5989579880bf80df31df46483304Patrick Dubroy public void draw(Canvas canvas) { 269bdb5c5342adc550559fd723af461e53248f2fba8Michael Jurka final Drawable background = mBackground; 270bdb5c5342adc550559fd723af461e53248f2fba8Michael Jurka if (background != null) { 2718b805b17158886035b38261eb611d8641701ae43Michael Jurka final int scrollX = getScrollX(); 2728b805b17158886035b38261eb611d8641701ae43Michael Jurka final int scrollY = getScrollY(); 273bdb5c5342adc550559fd723af461e53248f2fba8Michael Jurka 274bdb5c5342adc550559fd723af461e53248f2fba8Michael Jurka if (mBackgroundSizeChanged) { 2758b805b17158886035b38261eb611d8641701ae43Michael Jurka background.setBounds(0, 0, getRight() - getLeft(), getBottom() - getTop()); 276bdb5c5342adc550559fd723af461e53248f2fba8Michael Jurka mBackgroundSizeChanged = false; 277bdb5c5342adc550559fd723af461e53248f2fba8Michael Jurka } 278bdb5c5342adc550559fd723af461e53248f2fba8Michael Jurka 279bdb5c5342adc550559fd723af461e53248f2fba8Michael Jurka if ((scrollX | scrollY) == 0) { 280bdb5c5342adc550559fd723af461e53248f2fba8Michael Jurka background.draw(canvas); 281bdb5c5342adc550559fd723af461e53248f2fba8Michael Jurka } else { 282bdb5c5342adc550559fd723af461e53248f2fba8Michael Jurka canvas.translate(scrollX, scrollY); 283bdb5c5342adc550559fd723af461e53248f2fba8Michael Jurka background.draw(canvas); 284bdb5c5342adc550559fd723af461e53248f2fba8Michael Jurka canvas.translate(-scrollX, -scrollY); 28531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 28607f2e81d77b5f788e1d812011ea3d5b74acde4e4Winson Chung } 2870dca1ec41479a74f8da080224fa0c7eacab674d6Andrew Flynn 2880dca1ec41479a74f8da080224fa0c7eacab674d6Andrew Flynn // If text is transparent, don't draw any shadow 289bc239a15464f543a41b960b946aa77258454efafAndrew Flynn if (getCurrentTextColor() == getResources().getColor(android.R.color.transparent)) { 2900dca1ec41479a74f8da080224fa0c7eacab674d6Andrew Flynn getPaint().clearShadowLayer(); 2910dca1ec41479a74f8da080224fa0c7eacab674d6Andrew Flynn super.draw(canvas); 2920dca1ec41479a74f8da080224fa0c7eacab674d6Andrew Flynn return; 2930dca1ec41479a74f8da080224fa0c7eacab674d6Andrew Flynn } 2940dca1ec41479a74f8da080224fa0c7eacab674d6Andrew Flynn 295bdb5c5342adc550559fd723af461e53248f2fba8Michael Jurka // We enhance the shadow by drawing the shadow twice 296e7e3f6c438a9de1d4a0557962f868d9a01f56286Michael Jurka getPaint().setShadowLayer(SHADOW_LARGE_RADIUS, 0.0f, SHADOW_Y_OFFSET, SHADOW_LARGE_COLOUR); 297bdb5c5342adc550559fd723af461e53248f2fba8Michael Jurka super.draw(canvas); 298bdb5c5342adc550559fd723af461e53248f2fba8Michael Jurka canvas.save(Canvas.CLIP_SAVE_FLAG); 2998b805b17158886035b38261eb611d8641701ae43Michael Jurka canvas.clipRect(getScrollX(), getScrollY() + getExtendedPaddingTop(), 3008b805b17158886035b38261eb611d8641701ae43Michael Jurka getScrollX() + getWidth(), 3018b805b17158886035b38261eb611d8641701ae43Michael Jurka getScrollY() + getHeight(), Region.Op.INTERSECT); 302e7e3f6c438a9de1d4a0557962f868d9a01f56286Michael Jurka getPaint().setShadowLayer(SHADOW_SMALL_RADIUS, 0.0f, 0.0f, SHADOW_SMALL_COLOUR); 303bdb5c5342adc550559fd723af461e53248f2fba8Michael Jurka super.draw(canvas); 304bdb5c5342adc550559fd723af461e53248f2fba8Michael Jurka canvas.restore(); 30531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 3069c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato 3079c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato @Override 3089c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato protected void onAttachedToWindow() { 3099c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato super.onAttachedToWindow(); 310656d11c882296d732e6bdab30ec26f84b99eba19Winson Chung if (mBackground != null) mBackground.setCallback(this); 3119c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato } 3129c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato 3139c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato @Override 3149c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato protected void onDetachedFromWindow() { 3159c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato super.onDetachedFromWindow(); 316656d11c882296d732e6bdab30ec26f84b99eba19Winson Chung if (mBackground != null) mBackground.setCallback(null); 3179c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato } 318affd7b4d23cecb4ed74133dd8bd9a5ede099c562Winson Chung 319affd7b4d23cecb4ed74133dd8bd9a5ede099c562Winson Chung @Override 320affd7b4d23cecb4ed74133dd8bd9a5ede099c562Winson Chung protected boolean onSetAlpha(int alpha) { 321e22a8e9d3eafe569fe0f4d284c77af08c6e2fe28Winson Chung if (mPrevAlpha != alpha) { 322e22a8e9d3eafe569fe0f4d284c77af08c6e2fe28Winson Chung mPrevAlpha = alpha; 323e22a8e9d3eafe569fe0f4d284c77af08c6e2fe28Winson Chung super.onSetAlpha(alpha); 324e22a8e9d3eafe569fe0f4d284c77af08c6e2fe28Winson Chung } 325e22a8e9d3eafe569fe0f4d284c77af08c6e2fe28Winson Chung return true; 326affd7b4d23cecb4ed74133dd8bd9a5ede099c562Winson Chung } 32788f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung 32888f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung @Override 32988f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung public void cancelLongPress() { 33088f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung super.cancelLongPress(); 33188f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung 33288f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung mLongPressHelper.cancelLongPress(); 33388f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung } 33431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project} 335