制作一个半透明遮罩层的库——TipView
效果图
知识点
要实现这个自定义ViewGroup,需要知道几点知识:
- DecorView 是什么?
- 在 DecorView 上添加 View 之后,如何防止点击事件被透传到 content_view?
- Canvas和Bitmap的关系
- ViewGroup 不会调用 onDraw() 要如何解决?
- 如何绘制阴影加空洞?
- ondraw() 和dispatchdraw()的区别
public class TipView extends RelativeLayout {
public TipView(Context context) {
super(context);
/*
* let ViewGroup to invoke onDraw() method,
* also, you can override dispatchDraw() method instead of override onDraw() method
*/
setWillNotDraw(false);
mMaskPaint = new Paint();
mMaskPaint.setColor(0xC8000000);
mTransparentPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mTransparentPaint.setColor(Color.TRANSPARENT);
mPorterDuffXfermode = new PorterDuffXfermode(PorterDuff.Mode.CLEAR);
mTransparentPaint.setXfermode(mPorterDuffXfermode);
mSystemCanvasPaint = new Paint();
}
private Bitmap mMaskBitmap;
private Canvas mMaskCanvas;
private Paint mMaskPaint;
private Paint mTransparentPaint;
private PorterDuffXfermode mPorterDuffXfermode;
private Paint mSystemCanvasPaint;
@Override
protected void onDraw(Canvas systemCanvas) {
super.onDraw(systemCanvas);
// 绘制遮罩层
if (mMaskBitmap == null) {
mMaskBitmap = Bitmap.createBitmap(systemCanvas.getWidth(), systemCanvas.getHeight(), Bitmap.Config.ARGB_8888);
mMaskCanvas = new Canvas(mMaskBitmap);
}
mMaskCanvas.drawRect(0, 0, mMaskCanvas.getWidth(), mMaskCanvas.getHeight(), mMaskPaint);
// 在遮罩层上挖一个洞
mMaskCanvas.drawCircle(180, 230, 100, mTransparentPaint);
systemCanvas.drawBitmap(mMaskBitmap, 0, 0, mSystemCanvasPaint);
}
}
调用
TipView tipView = new TipView(this);
tipView.setClickable(true); // 防止点击事件被透传到 content_view
((ViewGroup) getWindow().getDecorView()).addView(tipView);