FakeShadowDrawablepublic class FakeShadowDrawable extends android.graphics.drawable.Drawable A rounded rectangle drawable which also includes a shadow around. This is mostly copied from
frameworks/support/v7/cardview/eclair-mr1/android/support/v7/widget/
RoundRectDrawableWithShadow.java revision c42ba8c000d1e6ce85e152dfc17089a0a69e739f with a few
modifications to suit our needs in SystemUI. |
Fields Summary |
---|
static final double | COS_45 | static final float | SHADOW_MULTIPLIER | final float | mInsetShadow | android.graphics.Paint | mCornerShadowPaint | android.graphics.Paint | mEdgeShadowPaint | final android.graphics.RectF | mCardBounds | float | mCornerRadius | android.graphics.Path | mCornerShadowPath | float | mMaxShadowSize | float | mRawMaxShadowSize | float | mShadowSize | float | mRawShadowSize | private boolean | mDirty | private final int | mShadowStartColor | private final int | mShadowEndColor | private boolean | mAddPaddingForCorners | private boolean | mPrintedShadowClipWarningIf shadow size is set to a value above max shadow, we print a warning |
Constructors Summary |
---|
public FakeShadowDrawable(android.content.res.Resources resources, com.android.systemui.recents.RecentsConfiguration config)
mShadowStartColor = resources.getColor(R.color.fake_shadow_start_color);
mShadowEndColor = resources.getColor(R.color.fake_shadow_end_color);
mInsetShadow = resources.getDimension(R.dimen.fake_shadow_inset);
setShadowSize(resources.getDimensionPixelSize(R.dimen.fake_shadow_size),
resources.getDimensionPixelSize(R.dimen.fake_shadow_size));
mCornerShadowPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
mCornerShadowPaint.setStyle(Paint.Style.FILL);
mCornerShadowPaint.setDither(true);
mCornerRadius = config.taskViewRoundedCornerRadiusPx;
mCardBounds = new RectF();
mEdgeShadowPaint = new Paint(mCornerShadowPaint);
|
Methods Summary |
---|
private void | buildComponents(android.graphics.Rect bounds)
// Card is offset SHADOW_MULTIPLIER * maxShadowSize to account for the shadow shift.
// We could have different top-bottom offsets to avoid extra gap above but in that case
// center aligning Views inside the CardView would be problematic.
final float verticalOffset = mMaxShadowSize * SHADOW_MULTIPLIER;
mCardBounds.set(bounds.left + mMaxShadowSize, bounds.top + verticalOffset,
bounds.right - mMaxShadowSize, bounds.bottom - verticalOffset);
buildShadowCorners();
| private void | buildShadowCorners()
RectF innerBounds = new RectF(-mCornerRadius, -mCornerRadius, mCornerRadius, mCornerRadius);
RectF outerBounds = new RectF(innerBounds);
outerBounds.inset(-mShadowSize, -mShadowSize);
if (mCornerShadowPath == null) {
mCornerShadowPath = new Path();
} else {
mCornerShadowPath.reset();
}
mCornerShadowPath.setFillType(Path.FillType.EVEN_ODD);
mCornerShadowPath.moveTo(-mCornerRadius, 0);
mCornerShadowPath.rLineTo(-mShadowSize, 0);
// outer arc
mCornerShadowPath.arcTo(outerBounds, 180f, 90f, false);
// inner arc
mCornerShadowPath.arcTo(innerBounds, 270f, -90f, false);
mCornerShadowPath.close();
float startRatio = mCornerRadius / (mCornerRadius + mShadowSize);
mCornerShadowPaint.setShader(new RadialGradient(0, 0, mCornerRadius + mShadowSize,
new int[]{mShadowStartColor, mShadowStartColor, mShadowEndColor},
new float[]{0f, startRatio, 1f}
, Shader.TileMode.CLAMP));
// we offset the content shadowSize/2 pixels up to make it more realistic.
// this is why edge shadow shader has some extra space
// When drawing bottom edge shadow, we use that extra space.
mEdgeShadowPaint.setShader(new LinearGradient(0, -mCornerRadius + mShadowSize, 0,
-mCornerRadius - mShadowSize,
new int[]{mShadowStartColor, mShadowStartColor, mShadowEndColor},
new float[]{0f, .5f, 1f}, Shader.TileMode.CLAMP));
| static float | calculateHorizontalPadding(float maxShadowSize, float cornerRadius, boolean addPaddingForCorners)
if (addPaddingForCorners) {
return (float) (maxShadowSize + (1 - COS_45) * cornerRadius);
} else {
return maxShadowSize;
}
| static float | calculateVerticalPadding(float maxShadowSize, float cornerRadius, boolean addPaddingForCorners)
if (addPaddingForCorners) {
return (float) (maxShadowSize * SHADOW_MULTIPLIER + (1 - COS_45) * cornerRadius);
} else {
return maxShadowSize * SHADOW_MULTIPLIER;
}
| public void | draw(android.graphics.Canvas canvas)
if (mDirty) {
buildComponents(getBounds());
mDirty = false;
}
canvas.translate(0, mRawShadowSize / 4);
drawShadow(canvas);
canvas.translate(0, -mRawShadowSize / 4);
| private void | drawShadow(android.graphics.Canvas canvas)
final float edgeShadowTop = -mCornerRadius - mShadowSize;
final float inset = mCornerRadius + mInsetShadow + mRawShadowSize / 2;
final boolean drawHorizontalEdges = mCardBounds.width() - 2 * inset > 0;
final boolean drawVerticalEdges = mCardBounds.height() - 2 * inset > 0;
// LT
int saved = canvas.save();
canvas.translate(mCardBounds.left + inset, mCardBounds.top + inset);
canvas.drawPath(mCornerShadowPath, mCornerShadowPaint);
if (drawHorizontalEdges) {
canvas.drawRect(0, edgeShadowTop,
mCardBounds.width() - 2 * inset, -mCornerRadius,
mEdgeShadowPaint);
}
canvas.restoreToCount(saved);
// RB
saved = canvas.save();
canvas.translate(mCardBounds.right - inset, mCardBounds.bottom - inset);
canvas.rotate(180f);
canvas.drawPath(mCornerShadowPath, mCornerShadowPaint);
if (drawHorizontalEdges) {
canvas.drawRect(0, edgeShadowTop,
mCardBounds.width() - 2 * inset, -mCornerRadius + mShadowSize,
mEdgeShadowPaint);
}
canvas.restoreToCount(saved);
// LB
saved = canvas.save();
canvas.translate(mCardBounds.left + inset, mCardBounds.bottom - inset);
canvas.rotate(270f);
canvas.drawPath(mCornerShadowPath, mCornerShadowPaint);
if (drawVerticalEdges) {
canvas.drawRect(0, edgeShadowTop,
mCardBounds.height() - 2 * inset, -mCornerRadius, mEdgeShadowPaint);
}
canvas.restoreToCount(saved);
// RT
saved = canvas.save();
canvas.translate(mCardBounds.right - inset, mCardBounds.top + inset);
canvas.rotate(90f);
canvas.drawPath(mCornerShadowPath, mCornerShadowPaint);
if (drawVerticalEdges) {
canvas.drawRect(0, edgeShadowTop,
mCardBounds.height() - 2 * inset, -mCornerRadius, mEdgeShadowPaint);
}
canvas.restoreToCount(saved);
| float | getMinHeight()
final float content = 2 * Math.max(mRawMaxShadowSize, mCornerRadius + mInsetShadow
+ mRawMaxShadowSize * SHADOW_MULTIPLIER / 2);
return content + (mRawMaxShadowSize * SHADOW_MULTIPLIER + mInsetShadow) * 2;
| float | getMinWidth()
final float content = 2 *
Math.max(mRawMaxShadowSize, mCornerRadius + mInsetShadow + mRawMaxShadowSize / 2);
return content + (mRawMaxShadowSize + mInsetShadow) * 2;
| public int | getOpacity()
return PixelFormat.OPAQUE;
| public boolean | getPadding(android.graphics.Rect padding)
int vOffset = (int) Math.ceil(calculateVerticalPadding(mRawMaxShadowSize, mCornerRadius,
mAddPaddingForCorners));
int hOffset = (int) Math.ceil(calculateHorizontalPadding(mRawMaxShadowSize, mCornerRadius,
mAddPaddingForCorners));
padding.set(hOffset, vOffset, hOffset, vOffset);
return true;
| protected void | onBoundsChange(android.graphics.Rect bounds)
super.onBoundsChange(bounds);
mDirty = true;
| public void | setAlpha(int alpha)
mCornerShadowPaint.setAlpha(alpha);
mEdgeShadowPaint.setAlpha(alpha);
| public void | setColorFilter(android.graphics.ColorFilter cf)
mCornerShadowPaint.setColorFilter(cf);
mEdgeShadowPaint.setColorFilter(cf);
| void | setShadowSize(float shadowSize, float maxShadowSize)
if (shadowSize < 0 || maxShadowSize < 0) {
throw new IllegalArgumentException("invalid shadow size");
}
if (shadowSize > maxShadowSize) {
shadowSize = maxShadowSize;
if (!mPrintedShadowClipWarning) {
Log.w("CardView", "Shadow size is being clipped by the max shadow size. See "
+ "{CardView#setMaxCardElevation}.");
mPrintedShadowClipWarning = true;
}
}
if (mRawShadowSize == shadowSize && mRawMaxShadowSize == maxShadowSize) {
return;
}
mRawShadowSize = shadowSize;
mRawMaxShadowSize = maxShadowSize;
mShadowSize = shadowSize * SHADOW_MULTIPLIER + mInsetShadow;
mMaxShadowSize = maxShadowSize + mInsetShadow;
mDirty = true;
invalidateSelf();
|
|