14fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal/* 24fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal * Copyright (C) 2014 The Android Open Source Project 34fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal * 44fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal * Licensed under the Apache License, Version 2.0 (the "License"); 54fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal * you may not use this file except in compliance with the License. 64fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal * You may obtain a copy of the License at 74fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal * 84fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal * http://www.apache.org/licenses/LICENSE-2.0 94fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal * 104fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal * Unless required by applicable law or agreed to in writing, software 114fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal * distributed under the License is distributed on an "AS IS" BASIS, 124fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal * See the License for the specific language governing permissions and 144fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal * limitations under the License. 154fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal */ 164fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal 174fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyalpackage com.android.launcher3; 184fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal 194fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyalimport android.content.Context; 204fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyalimport android.graphics.Bitmap; 214fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyalimport android.graphics.Canvas; 224fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyalimport android.graphics.Color; 234fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyalimport android.graphics.Paint; 24be9798b6a2ef7c2c827a612203d81c67b3ec81acWinsonimport android.graphics.Rect; 254fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyalimport android.view.View; 264ffec48dec5da7bcf719ac0c37ee5e58f9ea2c1aSunny Goyalimport android.view.ViewDebug; 274fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyalimport android.view.ViewGroup; 284fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal 294fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyalpublic class ClickShadowView extends View { 304fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal 314fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal private static final int SHADOW_SIZE_FACTOR = 3; 324fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal private static final int SHADOW_LOW_ALPHA = 30; 334fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal private static final int SHADOW_HIGH_ALPHA = 60; 344fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal 354fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal private final Paint mPaint; 364fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal 374ffec48dec5da7bcf719ac0c37ee5e58f9ea2c1aSunny Goyal @ViewDebug.ExportedProperty(category = "launcher") 384fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal private final float mShadowOffset; 394ffec48dec5da7bcf719ac0c37ee5e58f9ea2c1aSunny Goyal @ViewDebug.ExportedProperty(category = "launcher") 404fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal private final float mShadowPadding; 414fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal 424fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal private Bitmap mBitmap; 434fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal 444fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal public ClickShadowView(Context context) { 454fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal super(context); 464fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal mPaint = new Paint(Paint.FILTER_BITMAP_FLAG); 474fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal mPaint.setColor(Color.BLACK); 484fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal 494fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal mShadowPadding = getResources().getDimension(R.dimen.blur_size_click_shadow); 504fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal mShadowOffset = getResources().getDimension(R.dimen.click_shadow_high_shift); 514fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal } 524fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal 534fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal /** 544fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal * @return extra space required by the view to show the shadow. 554fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal */ 564fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal public int getExtraSize() { 574fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal return (int) (SHADOW_SIZE_FACTOR * mShadowPadding); 584fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal } 594fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal 604fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal /** 614fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal * Applies the new bitmap. 624fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal * @return true if the view was invalidated. 634fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal */ 644fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal public boolean setBitmap(Bitmap b) { 654fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal if (b != mBitmap){ 664fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal mBitmap = b; 674fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal invalidate(); 684fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal return true; 694fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal } 704fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal return false; 714fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal } 724fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal 734fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal @Override 744fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal protected void onDraw(Canvas canvas) { 754fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal if (mBitmap != null) { 764fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal mPaint.setAlpha(SHADOW_LOW_ALPHA); 774fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal canvas.drawBitmap(mBitmap, 0, 0, mPaint); 784fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal mPaint.setAlpha(SHADOW_HIGH_ALPHA); 794fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal canvas.drawBitmap(mBitmap, 0, mShadowOffset, mPaint); 804fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal } 814fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal } 824fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal 834fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal public void animateShadow() { 844fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal setAlpha(0); 854fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal animate().alpha(1) 864fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal .setDuration(FastBitmapDrawable.CLICK_FEEDBACK_DURATION) 874fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal .setInterpolator(FastBitmapDrawable.CLICK_FEEDBACK_INTERPOLATOR) 884fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal .start(); 894fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal } 904fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal 914fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal /** 924fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal * Aligns the shadow with {@param view} 934fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal * @param viewParent immediate parent of {@param view}. It must be a sibling of this view. 944fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal */ 95be9798b6a2ef7c2c827a612203d81c67b3ec81acWinson public void alignWithIconView(BubbleTextView view, ViewGroup viewParent, View clipAgainstView) { 964fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal float leftShift = view.getLeft() + viewParent.getLeft() - getLeft(); 974fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal float topShift = view.getTop() + viewParent.getTop() - getTop(); 984fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal int iconWidth = view.getRight() - view.getLeft(); 99be9798b6a2ef7c2c827a612203d81c67b3ec81acWinson int iconHeight = view.getBottom() - view.getTop(); 1004fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal int iconHSpace = iconWidth - view.getCompoundPaddingRight() - view.getCompoundPaddingLeft(); 1014fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal float drawableWidth = view.getIcon().getBounds().width(); 1024fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal 103be9798b6a2ef7c2c827a612203d81c67b3ec81acWinson if (clipAgainstView != null) { 104be9798b6a2ef7c2c827a612203d81c67b3ec81acWinson // Set the bounds to clip against 105be9798b6a2ef7c2c827a612203d81c67b3ec81acWinson int[] coords = new int[] {0, 0}; 106be9798b6a2ef7c2c827a612203d81c67b3ec81acWinson Utilities.getDescendantCoordRelativeToAncestor(clipAgainstView, (View) getParent(), 107be9798b6a2ef7c2c827a612203d81c67b3ec81acWinson coords, false); 108be9798b6a2ef7c2c827a612203d81c67b3ec81acWinson int clipLeft = (int) Math.max(0, coords[0] - leftShift - mShadowPadding); 109be9798b6a2ef7c2c827a612203d81c67b3ec81acWinson int clipTop = (int) Math.max(0, coords[1] - topShift - mShadowPadding) ; 110be9798b6a2ef7c2c827a612203d81c67b3ec81acWinson setClipBounds(new Rect(clipLeft, clipTop, clipLeft + iconWidth, clipTop + iconHeight)); 111be9798b6a2ef7c2c827a612203d81c67b3ec81acWinson } else { 112be9798b6a2ef7c2c827a612203d81c67b3ec81acWinson // Reset the clip bounds 113be9798b6a2ef7c2c827a612203d81c67b3ec81acWinson setClipBounds(null); 114be9798b6a2ef7c2c827a612203d81c67b3ec81acWinson } 115be9798b6a2ef7c2c827a612203d81c67b3ec81acWinson 1164fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal setTranslationX(leftShift 1174eda8048c1705a716e8f2b9ddaf026a8a8b03863Winson Chung + viewParent.getTranslationX() 1184fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal + view.getCompoundPaddingLeft() * view.getScaleX() 1194fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal + (iconHSpace - drawableWidth) * view.getScaleX() / 2 /* drawable gap */ 1204fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal + iconWidth * (1 - view.getScaleX()) / 2 /* gap due to scale */ 1214fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal - mShadowPadding /* extra shadow size */ 1224fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal ); 1234fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal setTranslationY(topShift 1244eda8048c1705a716e8f2b9ddaf026a8a8b03863Winson Chung + viewParent.getTranslationY() 1254fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal + view.getPaddingTop() * view.getScaleY() /* drawable gap */ 1264fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal + view.getHeight() * (1 - view.getScaleY()) / 2 /* gap due to scale */ 1274fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal - mShadowPadding /* extra shadow size */ 1284fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal ); 1294fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal } 1304fe5a37dda8eb1869f9328d94236eb2c23f8109cSunny Goyal} 131