Home | History | Annotate | Download | only in activityanim
      1 /*
      2  * Copyright (C) 2013 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.example.android.activityanim;
     18 
     19 import android.content.Context;
     20 import android.graphics.Bitmap;
     21 import android.graphics.BlurMaskFilter;
     22 import android.graphics.BlurMaskFilter.Blur;
     23 import android.graphics.Canvas;
     24 import android.graphics.Color;
     25 import android.graphics.Paint;
     26 import android.graphics.Paint.Style;
     27 import android.graphics.Rect;
     28 import android.graphics.RectF;
     29 import android.util.AttributeSet;
     30 import android.view.View;
     31 import android.widget.RelativeLayout;
     32 
     33 /**
     34  * This custom layout paints a drop shadow behind all children. The size and opacity
     35  * of the drop shadow is determined by a "depth" factor that can be set and animated.
     36  */
     37 public class ShadowLayout extends RelativeLayout {
     38 
     39     Paint mShadowPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
     40     float mShadowDepth;
     41     Bitmap mShadowBitmap;
     42     static final int BLUR_RADIUS = 6;
     43     static final RectF sShadowRectF = new RectF(0, 0, 200, 200);
     44     static final Rect sShadowRect = new Rect(0, 0, 200 + 2 * BLUR_RADIUS, 200 + 2 * BLUR_RADIUS);
     45     static RectF tempShadowRectF = new RectF(0, 0, 0, 0);
     46 
     47     public ShadowLayout(Context context, AttributeSet attrs, int defStyle) {
     48         super(context, attrs, defStyle);
     49         init();
     50     }
     51 
     52     public ShadowLayout(Context context, AttributeSet attrs) {
     53         super(context, attrs);
     54         init();
     55     }
     56 
     57     public ShadowLayout(Context context) {
     58         super(context);
     59         init();
     60     }
     61 
     62     /**
     63      * Called by the constructors - sets up the drawing parameters for the drop shadow.
     64      */
     65     private void init() {
     66         mShadowPaint.setColor(Color.BLACK);
     67         mShadowPaint.setStyle(Style.FILL);
     68         setWillNotDraw(false);
     69         mShadowBitmap = Bitmap.createBitmap(sShadowRect.width(),
     70                 sShadowRect.height(), Bitmap.Config.ARGB_8888);
     71         Canvas c = new Canvas(mShadowBitmap);
     72         mShadowPaint.setMaskFilter(new BlurMaskFilter(BLUR_RADIUS, Blur.NORMAL));
     73         c.translate(BLUR_RADIUS, BLUR_RADIUS);
     74         c.drawRoundRect(sShadowRectF, sShadowRectF.width() / 40,
     75                 sShadowRectF.height() / 40, mShadowPaint);
     76     }
     77 
     78     /**
     79      * The "depth" factor determines the offset distance and opacity of the shadow (shadows that
     80      * are further away from the source are offset greater and are more translucent).
     81      * @param depth
     82      */
     83     public void setShadowDepth(float depth) {
     84         if (depth != mShadowDepth) {
     85             mShadowDepth = depth;
     86             mShadowPaint.setAlpha((int) (100 + 150 * (1 - mShadowDepth)));
     87             invalidate(); // We need to redraw when the shadow attributes change
     88         }
     89     }
     90 
     91     /**
     92      * Overriding onDraw allows us to draw shadows behind every child of this container.
     93      * onDraw() is called to draw a layout's content before the children are drawn, so the
     94      * shadows will be drawn first, behind the children (which is what we want).
     95      */
     96     @Override
     97     protected void onDraw(Canvas canvas) {
     98         for (int i = 0; i < getChildCount(); ++i) {
     99             View child = getChildAt(i);
    100             if (child.getVisibility() != View.VISIBLE || child.getAlpha() == 0) {
    101                 continue;
    102             }
    103             int depthFactor = (int) (80 * mShadowDepth);
    104             canvas.save();
    105             canvas.translate(child.getLeft() + depthFactor,
    106                     child.getTop() + depthFactor);
    107             canvas.concat(child.getMatrix());
    108             tempShadowRectF.right = child.getWidth();
    109             tempShadowRectF.bottom = child.getHeight();
    110             canvas.drawBitmap(mShadowBitmap, sShadowRect, tempShadowRectF, mShadowPaint);
    111             canvas.restore();
    112         }
    113     }
    114 
    115 
    116 }
    117