自定义蒙层挖空效果
在项目中,我们经常会遇到加盖蒙层的效果。当然,如果懒得话解决方法很简单,直接和UI要一张图片就搞定了。但图片比较占内存。如果内存比较紧张,这个时候,就考虑自己用代码实现了。
package com.jdjr.jdcn.demo.ext.widget;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.FrameLayout;
import com.jdjr.jdcn.demo.ext.R;
/**
* Created by qishuaishuai on 2017/12/4.
*/
public class FrameLayoutWithHole extends FrameLayout {
private Bitmap mEraserBitmap;
private Canvas mEraserCanvas;
private Paint mEraser;
private float mDensity;
private Context mContext;
private float mRadius;
private int mBackgroundColor;
private float mRx;//默认在中心位置
private float mRy;
public FrameLayoutWithHole(@NonNull Context context) {
super(context);
mContext = context;
}
public FrameLayoutWithHole(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
mContext = context;
TypedArray ta = context.obtainStyledAttributes(attrs,R.styleable.FrameLayoutWithHole);
mBackgroundColor = ta.getColor(R.styleable.FrameLayoutWithHole_background_color,-1);
mRadius = ta.getFloat(R.styleable.FrameLayoutWithHole_hole_radius,0);
mRx = ta.getFloat(R.styleable.FrameLayoutWithHole_radius_x,0);
mRy = ta.getFloat(R.styleable.FrameLayoutWithHole_radius_y,0);
init(null,0);
ta.recycle();
}
public FrameLayoutWithHole(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public FrameLayoutWithHole(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
public FrameLayoutWithHole(Context context, int backgroundColor,int radius
,int rx,int ry){//半径位置
this(context);
mBackgroundColor = backgroundColor;
this.mRadius = radius;
this.mRx = rx;
this.mRy = ry;
init(null,0);
}
private void init(AttributeSet attrs, int defStyle) {
setWillNotDraw(false);
mDensity = mContext.getResources().getDisplayMetrics().density;
Point size = new Point();
size.x = mContext.getResources().getDisplayMetrics().widthPixels;
size.y = mContext.getResources().getDisplayMetrics().heightPixels;
mRx = mRx*mDensity;
mRy = mRy*mDensity;
mRx = mRx !=0 ? mRx: size.x/2;
mRy = mRy !=0 ? mRy: size.y/2;
mRadius = mRadius !=0 ?mRadius:150;
mRadius = mRadius*mDensity;
mBackgroundColor = mBackgroundColor !=-1?mBackgroundColor:Color.parseColor("#55000000");
mEraserBitmap = Bitmap.createBitmap(size.x, size.y, Bitmap.Config.ARGB_8888);
mEraserCanvas = new Canvas(mEraserBitmap);
mEraser = new Paint();
mEraser.setColor(0xFFFFFFFF);
mEraser.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
mEraser.setFlags(Paint.ANTI_ALIAS_FLAG);
Log.d("tourguide", "getHeight: " + size.y);
Log.d("tourguide", "getWidth: " + size.x);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mEraserBitmap.eraseColor(Color.TRANSPARENT);
mEraserCanvas.drawColor(mBackgroundColor);
mEraserCanvas.drawCircle(
mRx,
mRy,
mRadius, mEraser);
canvas.drawBitmap(mEraserBitmap, 0, 0, null);
}
}
先把整个代码贴出来,再逐一讲解如何使用。
这段代码改字tourguide, 因为不需要其他过多的功能,所以就把其他东西给删除了,只留了一个带有蒙层,中间镂空的布局。
- 新建一个布局文件FrameLayoutWithHole, 将上述代码复制进去。
- 上述的代码提供了两种实现方式,一是直接用java代码实现,可以直接new 一个布局文件,这样有个缺点就是布局不方便,想在蒙层上边添加一些提示之类的就比较麻烦了。所以我采用的是将其作为布局放入布局文件中,再xml中操作
- 想将其作为布局,其实也很简单。 在value中间夹中找到attr.xml, 如果没有,就新建一个。然后将下边这段代码放进去。
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="FrameLayoutWithHole">
<attr name="hole_radius" format="integer"/>
<attr name="background_color" format="color"/>
<attr name="radius_x" format="integer"/>
<attr name="radius_y" format="integer"/>
</declare-styleable>
</resources>
在布局文件里边就可以直接使用了。
hole_radius 为镂空圆的半径
background_color 为透明色背景
radius_x 为圆心的x 轴半径
radius_y 为圆心的y轴半径
大致效果图如图所示,