要實現的效果是在當前頁面上,顯示半透明的遮罩層,在任意位置實現鏤空的圓形,鏤空的位置能看到下面的頁面,鏤空的位置跟隨一張提示文字的圖片,效果如下:
實現步驟:
- 繪製半透明的背景:
- 繪製圓形
繪製文字圖片
具體的實現代碼如下:
1 繪製透明背景:
/**
* 創建遮罩層形狀
*
* @return
*/
private Bitmap makeSrcRect() {
Bitmap bm = Bitmap.createBitmap(mScreenWidth, mScreenHeight, Bitmap.Config.ARGB_8888);
Canvas canvcs = new Canvas(bm);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.BLACK);
canvcs.drawRect(new RectF(0, 0, mScreenWidth, mScreenHeight), paint);
return bm;
}
2 繪製鏤空的圓形
/**
* 創建鏤空層圓形形狀
* @return
*/
private Bitmap makeDstCircle() {
Bitmap bm = Bitmap.createBitmap(mScreenWidth, mScreenHeight, Bitmap.Config.ARGB_8888);
Canvas canvcs = new Canvas(bm);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.WHITE);
canvcs.drawCircle(mPiercedX, mPiercedY, mPiercedRadius, paint);
return bm;
}
3 繪製文字圖片
/**
* 創建提示提示信息文字圖片的bitmap
*
* @return
*/
private Bitmap createPromptBitmap() {
Bitmap bitmap = BitmapFactory.decodeResource(
getResources(), R.drawable.prompt); // 圖片建議放到drawable-mdpi 目錄下 這樣可以根據屏密度得到正確的縮放比例
int width = bitmap.getWidth();
int height = bitmap.getHeight();
DisplayMetrics dm = getResources().getDisplayMetrics(); // 獲取屏幕密度
float realScale = 1.0f / dm.density; // 恢復到實際像素的縮放
float settingScale = realScale;
if (realScale * width > mScreenWidth / 2) {
settingScale = 0.8f * mScreenWidth / width;
} else if (realScale * height > mScreenHeight) {
settingScale = 0.8f * mScreenHeight / height;
}
// 取得想要縮放的matrix參數
Matrix matrix = new Matrix();
matrix.postScale(settingScale, settingScale);
// 得到新的圖片
Bitmap newBitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);
return newBitmap;
}
最後的MaskPierceView 代碼如下:
public class MaskPierceView extends View {
private static final String TAG = "MaskPierceView";
private Bitmap mSrcRect;
private Bitmap mDstCircle;
private int mScreenWidth; // 屏幕的寬
private int mScreenHeight; // 屏幕的高
private int mPiercedX, mPiercedY;
private int mPiercedRadius;
public MaskPierceView(Context context) {
this(context, null);
}
public MaskPierceView(Context context, AttributeSet attrs) {
super(context, attrs);
ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
setLayoutParams(layoutParams);
if (mScreenWidth == 0) {
DisplayMetrics dm = getResources().getDisplayMetrics();
mScreenWidth = dm.widthPixels;
mScreenHeight = dm.heightPixels;
}
}
/**
* @param mPiercedX 鏤空的圓心座標
* @param mPiercedY 鏤空的圓心座標
* @param mPiercedRadius 鏤空的圓半徑
*/
public void setPiercePosition(int mPiercedX, int mPiercedY, int mPiercedRadius) {
this.mPiercedX = mPiercedX;
this.mPiercedY = mPiercedY;
this.mPiercedRadius = mPiercedRadius;
}
@Override
protected void onDraw(Canvas canvas) {
mSrcRect = makeSrcRect();
mDstCircle = makeDstCircle();
Paint paint = new Paint();
paint.setFilterBitmap(false);
canvas.saveLayer(0, 0, mScreenWidth, mScreenHeight, null,
Canvas.MATRIX_SAVE_FLAG |
Canvas.CLIP_SAVE_FLAG |
Canvas.HAS_ALPHA_LAYER_SAVE_FLAG |
Canvas.FULL_COLOR_LAYER_SAVE_FLAG |
Canvas.CLIP_TO_LAYER_SAVE_FLAG);
canvas.drawBitmap(mDstCircle, 0, 0, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT));
paint.setAlpha(160);
canvas.drawBitmap(mSrcRect, 0, 0, paint);
paint.setXfermode(null);
canvas.saveLayer(0, 0, mScreenWidth, mScreenHeight, null,
Canvas.MATRIX_SAVE_FLAG |
Canvas.CLIP_SAVE_FLAG |
Canvas.HAS_ALPHA_LAYER_SAVE_FLAG |
Canvas.FULL_COLOR_LAYER_SAVE_FLAG |
Canvas.CLIP_TO_LAYER_SAVE_FLAG);
paint.setAlpha(255);
canvas.drawBitmap(createPromptBitmap(), mPiercedX + mPiercedRadius, mPiercedY + mPiercedRadius, paint);
}
/**
* 創建鏤空層圓形形狀
* @return
*/
private Bitmap makeDstCircle() {
Bitmap bm = Bitmap.createBitmap(mScreenWidth, mScreenHeight, Bitmap.Config.ARGB_8888);
Canvas canvcs = new Canvas(bm);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.WHITE);
canvcs.drawCircle(mPiercedX, mPiercedY, mPiercedRadius, paint);
return bm;
}
/**
* 創建遮罩層形狀
*
* @return
*/
private Bitmap makeSrcRect() {
Bitmap bm = Bitmap.createBitmap(mScreenWidth, mScreenHeight, Bitmap.Config.ARGB_8888);
Canvas canvcs = new Canvas(bm);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.BLACK);
canvcs.drawRect(new RectF(0, 0, mScreenWidth, mScreenHeight), paint);
return bm;
}
/**
* 創建提示提示信息文字圖片的bitmap
*
* @return
*/
private Bitmap createPromptBitmap() {
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.prompt);
int width = bitmap.getWidth();
int height = bitmap.getHeight();
DisplayMetrics dm = getResources().getDisplayMetrics(); //獲取屏幕密度
float realScale = 1.0f / dm.density; //恢復到實際像素的縮放
float settingScale = realScale;
if (realScale * width > mScreenWidth / 2) {
settingScale = 0.8f * mScreenWidth / width;
} else if (realScale * height > mScreenHeight) {
settingScale = 0.8f * mScreenHeight / height;
}
// 取得想要縮放的matrix參數
Matrix matrix = new Matrix();
matrix.postScale(settingScale, settingScale);
// 得到新的圖片
Bitmap newBitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);
return newBitmap;
}
}