安卓背景 阴影遮罩_扩展Android的View类添加阴影效果

bd96500e110b49cbb3cd949968f18be7.png

I want to extend LinearLayout so that when my layout is drawn a drop shadow is added underneath it. I've played around overriding the onDraw method but I'm a bit lost. Any help with this or even library suggestions would be greatly appreciated!

Here's an example of the drop shadow view I am trying to achieve. I don't believe I can use a nine patch here because I need the contents of the view to be within the white box. This would mean I would need to know the distance between the border and the end of the PNG. However I believe different screen densities mean that this distance will always be the same PX but not the same DP.

So to be clear I need a way to extend the View class so that a drop shadow is drawn under it when it is added to a layout. No XML or 9Patch solutions please.

LWiYT.png

Thanks

Jack

解决方案

I agree with the comments on your question: programmatic dropshadow effect is a bad choice, and you could achieve the same effect with a simple 9patch (or a set of them) like stated here.

BTW I was too curious, and I ended with hacking a solution after work.

The code presented is a test, and should be intended as a simple proof-of-concept (so please don't downvote). Some of the operations shown are quite expensive, and may seriously impact on the performances (There are many examples around, look here, here to get an idea). It should be a last resort solution only for a component shown once-in-a-while.

public class BalloonView extends TextView {

protected NinePatchDrawable bg;

protected Paint paint;

protected Rect padding = new Rect();

protected Bitmap bmp;

public BalloonView(Context context) {

super(context);

init();

}

public BalloonView(Context context, AttributeSet attrs) {

super(context, attrs);

init();

}

public BalloonView(Context context, AttributeSet attrs, int defStyle) {

super(context, attrs, defStyle);

init();

}

@SuppressLint("NewApi")

protected void init() {

// decode the 9patch drawable

bg = (NinePatchDrawable) getResources().getDrawable(R.drawable.balloon);

// get paddings from the 9patch and apply them to the View

bg.getPadding(padding);

setPadding(padding.left, padding.top, padding.right, padding.bottom);

// prepare the Paint to use below

paint = new Paint();

paint.setAntiAlias(true);

paint.setColor(Color.rgb(255,255,255));

paint.setStyle(Style.FILL);

// this check is needed in order to get this code

// working if target SDK>=11

if( Build.VERSION.SDK_INT >= 11 )

setLayerType(View.LAYER_TYPE_SOFTWARE, paint);

// set the shadowLayer

paint.setShadowLayer(

padding.left * .2f, // radius

0f, // blurX

padding.left * .1f, // blurY

Color.argb(128, 0, 0, 0) // shadow color

);

}

@Override

protected void onDraw(Canvas canvas) {

int w = getMeasuredWidth();

int h = getMeasuredHeight();

// set 9patch bounds according to view measurement

// NOTE: if not set, the drawable will not be drawn

bg.setBounds(0, 0, w, h);

// this code looks expensive: let's do once

if( bmp == null ) {

// it seems like shadowLayer doesn't take into account

// alpha channel in ARGB_8888 sources...

bmp = Bitmap.createBitmap(w, h, Config.ARGB_8888);

// draw the given 9patch on the brand new bitmap

Canvas tmp = new Canvas(bmp);

bg.draw(tmp);

// extract only the alpha channel

bmp = bmp.extractAlpha();

}

// this "alpha mask" has the same shape of the starting 9patch,

// but filled in white and **with the dropshadow**!!!!

canvas.drawBitmap(bmp, 0, 0, paint);

// let's paint the 9patch over...

bg.draw(canvas);

super.onDraw(canvas);

}

}

First of all in order to get programmatic drop shadow you have to deal with Paint.setShadowLayer(...) like stated here. Basically you should define a shadow layer for the Paint object used to draw on the Canvas of your custom view. Unfortunately you cannot use a Paint object to draw a NinePatchDrawable, so you need to convert it into a Bitmap (1st hack). Furthermore it seems like shadow layers can't work properly with ARGB_8888 images, so the only way I found in order to get a proper shadow has been to draw the alpha mask of the given NinePatchDrawable (2nd hack) just below itself.

Here's a couple of sshots (tested on Android 2.3.3@mdpi and 4.2.2@xhdpi)

1FGP4.png

PnS9q.png

Edit: just to be thorough, I attached the 9patch used in the test (placed in res/drawable/mdpi)

qPghn.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值