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