Drawing an outer shadow when drawing an image
Here we go
Yup I still dig the Nexus S
First of all, please stop masking bitmaps that way, you can accomplish this without allocating another Bitmap
, checkout this blog post about how to draw rounded (and actually any shape) images.
Second using that Drawable
you probably can figure out how to add your shadow, just make sure it does not get clipped, on 18+ you could use ViewOverlay
s for that, also keep in mind that there are several unsupported drawing operations for hardware accelerated layers, that includes setShadowLayer
and BlurMaskFilter
, if performance is not an issue for you, you can disable it as always:
if (SDK_INT >= HONEYCOMB) {
view.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
And use setShadowLayer
as you were trying already:
somePaint.setShadowLayer(shadowSize, deltaX, deltaY, shadowColor);
For a sample please check the link at the end.
If you still want to be hardware accelerated you will have to fake it at risk of overdrawing, you could use a radial gradient or draw another oval blurring it yourself (as mentioned before can't use BlurMaskFilter
) or use a pre-blurred Bitmap
(more masking).
For such a subtle shadow I would rather just go flat if performance is required, the full sauce is in the banana stand.
Update: Starting L you can use real shadows.
ImageView imageView=findViewById(R.id.iv);
Bitmap icon = BitmapFactory.decodeResource(getResources(), R.drawable.images);
imageView.setImageBitmap(doHighlightImage(icon));
public static Bitmap doHighlightImage(Bitmap src) {
Bitmap bmOut = Bitmap.createBitmap(src.getWidth() + 96, src.getHeight() + 96, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bmOut);
canvas.drawColor(0, Mode.CLEAR);
Paint ptBlur = new Paint();
ptBlur.setMaskFilter(new BlurMaskFilter(15, BlurMaskFilter.Blur.NORMAL));
int[] offsetXY = new int[2];
Bitmap bmAlpha = src.extractAlpha(ptBlur, offsetXY);
Paint ptAlphaColor = new Paint();
ptAlphaColor.setColor(Color.BLACK);
canvas.drawBitmap(bmAlpha, offsetXY[0], offsetXY[1], ptAlphaColor);
bmAlpha.recycle();
canvas.drawBitmap(src, 0, 0, null);
return bmOut;
}
I wanted a similar effect, but on an AppWidget so unfortunately I couldn't use @EvelioTarazona's solution. This is what I came up with, it should work with a bitmap of any shape.
final Bitmap src = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
final Bitmap shadow = addShadow(src, src.getHeight(), src.getWidth(), Color.BLACK, 3, 1, 3);
final ImageView iv = (ImageView)findViewById(R.id.image);
iv.setImageBitmap(shadow);
public Bitmap addShadow(final Bitmap bm, final int dstHeight, final int dstWidth, int color, int size, float dx, float dy) {
final Bitmap mask = Bitmap.createBitmap(dstWidth, dstHeight, Config.ALPHA_8);
final Matrix scaleToFit = new Matrix();
final RectF src = new RectF(0, 0, bm.getWidth(), bm.getHeight());
final RectF dst = new RectF(0, 0, dstWidth - dx, dstHeight - dy);
scaleToFit.setRectToRect(src, dst, ScaleToFit.CENTER);
final Matrix dropShadow = new Matrix(scaleToFit);
dropShadow.postTranslate(dx, dy);
final Canvas maskCanvas = new Canvas(mask);
final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
maskCanvas.drawBitmap(bm, scaleToFit, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_OUT));
maskCanvas.drawBitmap(bm, dropShadow, paint);
final BlurMaskFilter filter = new BlurMaskFilter(size, Blur.NORMAL);
paint.reset();
paint.setAntiAlias(true);
paint.setColor(color);
paint.setMaskFilter(filter);
paint.setFilterBitmap(true);
final Bitmap ret = Bitmap.createBitmap(dstWidth, dstHeight, Config.ARGB_8888);
final Canvas retCanvas = new Canvas(ret);
retCanvas.drawBitmap(mask, 0, 0, paint);
retCanvas.drawBitmap(bm, scaleToFit, null);
mask.recycle();
return ret;
}