1 /*
2  * Copyright (C) 2014 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 
17 package com.android.launcher3;
18 
19 import android.content.Context;
20 import android.graphics.Bitmap;
21 import android.graphics.Canvas;
22 import android.graphics.Color;
23 import android.graphics.Paint;
24 import android.view.View;
25 import android.view.ViewGroup;
26 
27 public class ClickShadowView extends View {
28 
29     private static final int SHADOW_SIZE_FACTOR = 3;
30     private static final int SHADOW_LOW_ALPHA = 30;
31     private static final int SHADOW_HIGH_ALPHA = 60;
32 
33     private final Paint mPaint;
34 
35     private final float mShadowOffset;
36     private final float mShadowPadding;
37 
38     private Bitmap mBitmap;
39 
ClickShadowView(Context context)40     public ClickShadowView(Context context) {
41         super(context);
42         mPaint = new Paint(Paint.FILTER_BITMAP_FLAG);
43         mPaint.setColor(Color.BLACK);
44 
45         mShadowPadding = getResources().getDimension(R.dimen.blur_size_click_shadow);
46         mShadowOffset = getResources().getDimension(R.dimen.click_shadow_high_shift);
47     }
48 
49     /**
50      * @return extra space required by the view to show the shadow.
51      */
getExtraSize()52     public int getExtraSize() {
53         return (int) (SHADOW_SIZE_FACTOR * mShadowPadding);
54     }
55 
56     /**
57      * Applies the new bitmap.
58      * @return true if the view was invalidated.
59      */
setBitmap(Bitmap b)60     public boolean setBitmap(Bitmap b) {
61         if (b != mBitmap){
62             mBitmap = b;
63             invalidate();
64             return true;
65         }
66         return false;
67     }
68 
69     @Override
onDraw(Canvas canvas)70     protected void onDraw(Canvas canvas) {
71         if (mBitmap != null) {
72             mPaint.setAlpha(SHADOW_LOW_ALPHA);
73             canvas.drawBitmap(mBitmap, 0, 0, mPaint);
74             mPaint.setAlpha(SHADOW_HIGH_ALPHA);
75             canvas.drawBitmap(mBitmap, 0, mShadowOffset, mPaint);
76         }
77     }
78 
animateShadow()79     public void animateShadow() {
80         setAlpha(0);
81         animate().alpha(1)
82             .setDuration(FastBitmapDrawable.CLICK_FEEDBACK_DURATION)
83             .setInterpolator(FastBitmapDrawable.CLICK_FEEDBACK_INTERPOLATOR)
84             .start();
85     }
86 
87     /**
88      * Aligns the shadow with {@param view}
89      * @param viewParent immediate parent of {@param view}. It must be a sibling of this view.
90      */
alignWithIconView(BubbleTextView view, ViewGroup viewParent)91     public void alignWithIconView(BubbleTextView view, ViewGroup viewParent) {
92         float leftShift = view.getLeft() + viewParent.getLeft() - getLeft();
93         float topShift = view.getTop() + viewParent.getTop() - getTop();
94         int iconWidth = view.getRight() - view.getLeft();
95         int iconHSpace = iconWidth - view.getCompoundPaddingRight() - view.getCompoundPaddingLeft();
96         float drawableWidth = view.getIcon().getBounds().width();
97 
98         setTranslationX(leftShift
99                 + viewParent.getTranslationX()
100                 + view.getCompoundPaddingLeft() * view.getScaleX()
101                 + (iconHSpace - drawableWidth) * view.getScaleX() / 2  /* drawable gap */
102                 + iconWidth * (1 - view.getScaleX()) / 2  /* gap due to scale */
103                 - mShadowPadding  /* extra shadow size */
104                 );
105         setTranslationY(topShift
106                 + viewParent.getTranslationY()
107                 + view.getPaddingTop() * view.getScaleY()  /* drawable gap */
108                 + view.getHeight() * (1 - view.getScaleY()) / 2  /* gap due to scale */
109                 - mShadowPadding  /* extra shadow size */
110                 );
111     }
112 }
113