blob: b3bc9618093b762cb50be4179307e72a27b24c56 [file] [log] [blame]
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.android.activityanim;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BlurMaskFilter;
import android.graphics.BlurMaskFilter.Blur;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
import android.widget.RelativeLayout;
/**
* This custom layout paints a drop shadow behind all children. The size and opacity
* of the drop shadow is determined by a "depth" factor that can be set and animated.
*/
public class ShadowLayout extends RelativeLayout {
Paint mShadowPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
float mShadowDepth;
Bitmap mShadowBitmap;
static final int BLUR_RADIUS = 6;
static final RectF sShadowRectF = new RectF(0, 0, 200, 200);
static final Rect sShadowRect = new Rect(0, 0, 200 + 2 * BLUR_RADIUS, 200 + 2 * BLUR_RADIUS);
static RectF tempShadowRectF = new RectF(0, 0, 0, 0);
public ShadowLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public ShadowLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public ShadowLayout(Context context) {
super(context);
init();
}
/**
* Called by the constructors - sets up the drawing parameters for the drop shadow.
*/
private void init() {
mShadowPaint.setColor(Color.BLACK);
mShadowPaint.setStyle(Style.FILL);
setWillNotDraw(false);
mShadowBitmap = Bitmap.createBitmap(sShadowRect.width(),
sShadowRect.height(), Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(mShadowBitmap);
mShadowPaint.setMaskFilter(new BlurMaskFilter(BLUR_RADIUS, Blur.NORMAL));
c.translate(BLUR_RADIUS, BLUR_RADIUS);
c.drawRoundRect(sShadowRectF, sShadowRectF.width() / 40,
sShadowRectF.height() / 40, mShadowPaint);
}
/**
* The "depth" factor determines the offset distance and opacity of the shadow (shadows that
* are further away from the source are offset greater and are more translucent).
* @param depth
*/
public void setShadowDepth(float depth) {
if (depth != mShadowDepth) {
mShadowDepth = depth;
mShadowPaint.setAlpha((int) (100 + 150 * (1 - mShadowDepth)));
invalidate(); // We need to redraw when the shadow attributes change
}
}
/**
* Overriding onDraw allows us to draw shadows behind every child of this container.
* onDraw() is called to draw a layout's content before the children are drawn, so the
* shadows will be drawn first, behind the children (which is what we want).
*/
@Override
protected void onDraw(Canvas canvas) {
for (int i = 0; i < getChildCount(); ++i) {
View child = getChildAt(i);
if (child.getVisibility() != View.VISIBLE || child.getAlpha() == 0) {
continue;
}
int depthFactor = (int) (80 * mShadowDepth);
canvas.save();
canvas.translate(child.getLeft() + depthFactor,
child.getTop() + depthFactor);
canvas.concat(child.getMatrix());
tempShadowRectF.right = child.getWidth();
tempShadowRectF.bottom = child.getHeight();
canvas.drawBitmap(mShadowBitmap, sShadowRect, tempShadowRectF, mShadowPaint);
canvas.restore();
}
}
}