1. 鎖屏效果如下圖所示

2. 源碼及流程介紹
2.1 輔助線繪制
canvas.drawLine(0, standardY, canvas.getWidth(), standardY, paint);
paint.setColor(Color.BLUE);
canvas.drawLine(standardX, 0, standardX, canvas.getHeight(), paint);
2.2 繪制忽略,已讀Rect區(qū)域及繪制相關(guān)圖標(biāo)
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
/** 設(shè)置屏幕寬度高度等 */
DisplayMetrics dm = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(dm);
LeXingApplation.screenWidthPixels = dm.widthPixels;
LeXingApplation.screenHeightPixels = dm.heightPixels;
dm = null;
/*************/
if (!dataInitFlag) {
// 寬度中心取屏幕畫布的一半處
standardX = (int) (canvas.getWidth() / 2f);
// 高度取layout高度
canvasHeight = canvas.getHeight();
standardY = (int) (canvas.getHeight() / 1.2f);
ignoreAlarmX = (int) (canvas.getWidth() / 6f);
readAlarmX = (int) (canvas.getWidth() * 5f / 6f);
lockOffRecSrc.right = lockOffBitmap.getWidth();
lockOffRecSrc.bottom = lockOffBitmap.getHeight();
lockOffRecDst.left = standardX - lockOffHalfSize;
lockOffRecDst.top = standardY - lockOffHalfSize;
lockOffRecDst.right = standardX + lockOffHalfSize;
lockOffRecDst.bottom = standardY + lockOffHalfSize;
lockOnRecSrc.right = lockOnBitmap.getWidth();
lockOnRecSrc.bottom = lockOnBitmap.getHeight();
lockOnRecDst.left = standardX - lockOnHalfSize;
lockOnRecDst.top = standardY - lockOnHalfSize;
lockOnRecDst.right = standardX + lockOnHalfSize;
lockOnRecDst.bottom = standardY + lockOnHalfSize;
ignoreRecSrc.right = ignoreOffBitmap.getWidth();
ignoreRecSrc.bottom = ignoreOffBitmap.getHeight();
ignoreRecDst.left = ignoreAlarmX - ignoreReadHalfSize;
ignoreRecDst.top = standardY - ignoreReadHalfSize;
ignoreRecDst.right = ignoreAlarmX + ignoreReadHalfSize;
ignoreRecDst.bottom = standardY + ignoreReadHalfSize;
readRecSrc.right = readOffBitmap.getWidth();
readRecSrc.bottom = readOffBitmap.getHeight();
readRecDst.left = readAlarmX - ignoreReadHalfSize;
readRecDst.top = standardY - ignoreReadHalfSize;
readRecDst.right = readAlarmX + ignoreReadHalfSize;
readRecDst.bottom = standardY + ignoreReadHalfSize;
/*** alarm */
alarmOff2OnSrc.right = alarmOff2OnBitmap.getWidth();
alarmOff2OnSrc.bottom = alarmOff2OnBitmap.getHeight();
ignoreAlarmOff2OnDst.left = ignoreAlarmX - alarmOff2OnHalfSize;
ignoreAlarmOff2OnDst.top = standardY - alarmOff2OnHalfSize;
ignoreAlarmOff2OnDst.right = ignoreAlarmX + alarmOff2OnHalfSize;
ignoreAlarmOff2OnDst.bottom = standardY + alarmOff2OnHalfSize;
alarmOff2OnSrc.right = alarmOff2OnBitmap.getWidth();
alarmOff2OnSrc.bottom = alarmOff2OnBitmap.getHeight();
readAlarmOff2OnDst.left = readAlarmX - alarmOff2OnHalfSize;
readAlarmOff2OnDst.top = standardY - alarmOff2OnHalfSize;
readAlarmOff2OnDst.right = readAlarmX + alarmOff2OnHalfSize;
readAlarmOff2OnDst.bottom = standardY + alarmOff2OnHalfSize;
/** left view ***/
leftPlusRecSrc.right = leftPlusBitmap.getWidth();
leftPlusRecSrc.bottom = leftPlusBitmap.getHeight();
leftPlusRecDst.left = ignoreAlarmOff2OnDst.right;
leftPlusRecDst.top = standardY - plusHalfHeight;
// 減少分割線高度的距離
leftPlusRecDst.right = lockOffRecDst.left - plusHalfHeight * 2;
leftPlusRecDst.bottom = standardY + plusHalfHeight;
/*** right view **/
rightPlusRecSrc.right = rightPlusBitmap.getWidth();
rightPlusRecSrc.bottom = rightPlusBitmap.getHeight();
// 增加分割線高度的距離
rightPlusRecDst.left = lockOffRecDst.right + plusHalfHeight * 2;
rightPlusRecDst.top = standardY - plusHalfHeight;
rightPlusRecDst.right = readAlarmOff2OnDst.left;
rightPlusRecDst.bottom = standardY + plusHalfHeight;
lockScreenTopYTo = (int) (standardY * 1.2f - lockOnHalfSize);
// lockRecSrc,目標(biāo)矩形初始化
lockRecSrc = lockOffRecSrc;
lockRecDst = lockOffRecDst;
lockBitmap = lockOffBitmap;
// 中央鎖用的漸變的光圈
fadeInOnCenterLockSrc.right = fadeInOnCenterLockBitmap.getWidth();
fadeInOnCenterLockSrc.bottom = fadeInOnCenterLockBitmap.getHeight();
fadeInOnCenterLockDst.left = standardX - fadeInCenterLockHalfSize;
fadeInOnCenterLockDst.top = standardY - fadeInCenterLockHalfSize;
fadeInOnCenterLockDst.right = standardX + fadeInCenterLockHalfSize;
fadeInOnCenterLockDst.bottom = standardY + fadeInCenterLockHalfSize;
dataInitFlag = true;
}
if (ignoreOffBitmap != null && leftPlusBitmap != null
&& readOffBitmap != null && rightPlusBitmap != null) {
Log.e("tag", "x=" + standardX + "Y=" + standardY);
drawBitmapToCanvas(canvas);
} else {
drawBitmapToCanvas(canvas);
}
Paint paint = new Paint();
paint.setColor(Color.RED);
// 畫標(biāo)準(zhǔn)x y坐標(biāo)輔助線
canvas.drawLine(0, standardY, canvas.getWidth(), standardY, paint);
paint.setColor(Color.BLUE);
canvas.drawLine(standardX, 0, standardX, canvas.getHeight(), paint);
}
2.3?drawBitmapToCanvas方法繪制到canvas
public void drawBitmapToCanvas(Canvas canvas) {
// 畫ignore圖片
? if (ignoreOffBitmap !=null &&leftPlusBitmap !=null
? ? ? ? &&rightPlusBitmap !=null &&readOffBitmap !=null) {
// 左右圖標(biāo)與橫線的顯示狀態(tài)與中央鎖的光圈的顯示狀態(tài)相反
? ? ? if (!fadeInCenterLockFlag) {
canvas.drawBitmap(ignoreOffBitmap, ignoreRecSrc, ignoreRecDst,
? ? ? ? ? ? ? null);
? ? ? ? // 畫left plus圖片
? ? ? ? canvas.drawBitmap(leftPlusBitmap, leftPlusRecSrc,
? ? ? ? ? ? ? leftPlusRecDst, null);
? ? ? }
// 畫鎖圖片
? ? ? if (lockBitmap !=null) {
// 在鎖圖片touch move時(shí), 命中ignore或read圖片時(shí), 鎖圖片不需要繪制
? ? ? ? canvas.drawBitmap(lockBitmap, lockRecSrc, lockRecDst, null);
? ? ? ? // 畫鎖心在沒有被touchdown情況下外面的光圈
? ? ? ? if (fadeInCenterLockFlag) {
? ? ? ? ? ? ? ? ?canvas.drawBitmap(fadeInOnCenterLockBitmap,
? ? ? ? ? ? ? ? ? fadeInOnCenterLockSrc, fadeInOnCenterLockDst, null);
? ? ? ? }
}else {
Log.e("tag", "draw center bitmap is? null");
? ? ? }
// Log.e("tag", "lockRecDst bottom--" + lockRecDst.bottom + "top"
// + lockRecDst.top);
? ? ? // 左右圖標(biāo)與橫線的顯示狀態(tài)與中央鎖的光圈的顯示狀態(tài)相反
? ? ? if (!fadeInCenterLockFlag) {
// 畫right plus圖片
? ? ? ? canvas.drawBitmap(rightPlusBitmap, rightPlusRecSrc,
? ? ? ? ? ? ? rightPlusRecDst, null);
? ? ? ? // 畫read圖片
? ? ? ? canvas.drawBitmap(readOffBitmap, readRecSrc, readRecDst, null);
? ? ? }
// 畫命中的圈
? ? ? if (alarmHitBitmap !=null) {
// 命中的時(shí)候, 畫圈
? ? ? ? canvas.drawBitmap(alarmHitBitmap, alarmOff2OnSrc,
? ? ? ? ? ? ? alarmOff2OnDst, null);
? ? ? }
}else {
/** 轉(zhuǎn)碼得到bitmap,再繪制圖形 */
? ? ? decodeBitmapAndSave(hashMapBitmapArrayList);
? ? ? postInvalidate();
? }
}
2.4?獲得當(dāng)前point所在的Rect
private RectgetLockOnMoveRectDst(Point point) {
lockOnMoveRect.left = point.x -lockOnHalfSize;
? lockOnMoveRect.top = point.y -lockOnHalfSize;
? lockOnMoveRect.right = point.x +lockOnHalfSize;
? lockOnMoveRect.bottom = point.y +lockOnHalfSize;
? return lockOnMoveRect;
}
2.5?獲得當(dāng)前point所允許活動(dòng)的范圍內(nèi)的point, 超過邊界值, 則為邊界
private PointgetLockOnMoveAllowedPoint(Point point) {
int maxY = LeXingApplation.screenHeightPixels-lockOnHalfSize;
? int minY =standardY - (maxY -standardY);// standardY - (canvasHeight -
// standardY);
? // 判斷邊界
? // return new Point(point.x <= ignoreAlarmX ? ignoreAlarmX
// : (point.x >= readAlarmX ? readAlarmX : point.x),
// point.y <= lockOnHalfSize ? lockOnHalfSize
// : (point.y >= lockScreenTopYTo ? lockScreenTopYTo
// : point.y));
? // 判斷邊界
? return new Point(point.x <=ignoreAlarmX ?ignoreAlarmX
? ? ? ? : (point.x >=readAlarmX ?readAlarmX : point.x),
? ? ? ? point.y <=minY ?minY : (point.y >=maxY ?maxY : point.y));
}
2.6 兩點(diǎn)之間的距離計(jì)算
private int distance(int fromX, int fromY, int toX, int toY) {
return (int) Math.sqrt((toX - fromX) * (toX - fromX) + (toY - fromY)
* (toY - fromY));
}
2.7 onTouch處理,及圖標(biāo)替換
@Override
public boolean onTouch(View arg0, MotionEvent event) {
motionEventPoint.x = (int) event.getX();
? motionEventPoint.y = (int) event.getY();
switch (event.getAction()) {
? ? ? ?case MotionEvent.ACTION_DOWN: {
? ? ? ? // 重置命中l(wèi)ock圖標(biāo)標(biāo)志位
? ? ? ? ?touchDownHitFlag =false;
? ? ? ? // 判斷event是否命中鎖區(qū)域
? ? ? if (motionEventPoint.x >=lockOffRecDst.left
? ? ? ? ? ? &&motionEventPoint.x <=lockOffRecDst.right
? ? ? ? ? ? &&motionEventPoint.y >=lockOffRecDst.top
? ? ? ? ? ? &&motionEventPoint.y <=lockOffRecDst.bottom) {
// 切換為解鎖大圖
? ? ? ? touchDownHitFlag =true;
? ? ? ? fadeInCenterLockFlag =false;
? ? ? ? lockBitmap =lockOnBitmap;
? ? ? ? lockRecSrc =lockOnRecSrc;
? ? ? ? postInvalidate();
? ? ? }else {
lockBitmap =lockOffBitmap;
? ? ? }
// 每次touch down默認(rèn)不命中
? ?eventCode =null;
? }
break;
? case MotionEvent.ACTION_MOVE: {
if (touchDownHitFlag) {
// 只要鎖被拖動(dòng)的話, 光圈就不要
? ? ? ? fadeInCenterLockFlag =false;
? ? ? ? // 拖動(dòng)解鎖大圖
? ? ? ? // 大圖的四周不能越過邊界
? ? ? ? PointallowedPoint = getLockOnMoveAllowedPoint(motionEventPoint);
? ? ? ? //
? ? ? ? // 如果到達(dá)ignore圖片
? ? ? ? if (motionEventPoint.x
? ? ? ? ? ? ?// event與ignore之間的中心距離
? ? ? ? ? ? if (distance(allowedPoint.x, allowedPoint.y, ignoreAlarmX,
? ? ? ? ? ? ? ? ? standardY) <=eventHitDistance) {
? ? ? ? ? ? ? ? // 命中
? ? ? ? ? ? ? alarmHitBitmap =alarmOff2OnBitmap;
? ? ? ? ? ? ? alarmOff2OnDst =ignoreAlarmOff2OnDst;
? ? ? ? ? ? ? // 取消鎖圖標(biāo)的顯示
? ? ? ? ? ? ? lockBitmap =null;
? ? ? ? ? ? ? // 忽略報(bào)警事件code,equals(MSG_LAUNCH_IGNORE)
? ? ? ? ? ? ? eventCode =1;
? ? ? ? ? ? }else {
? ? ? ? ? ? ? // // 沒有命中, 忽略報(bào)警圖標(biāo)還原
? ? ? ? ? ? ? // ignoreBitmap = ignoreOffBitmap;
? ? ? ? ? ? ? // 打開鎖圖標(biāo)的顯示
? ? ? ? ? ? ? lockBitmap =lockOnBitmap;
? ? ? ? ? ? ? alarmHitBitmap =null;
? ? ? ? ? ? ? eventCode =null;
? ? ? ? ? ? }
}else {
// 如果到達(dá)read event與ignore之間的中心距離
? ? ? ? ? ? if (distance(allowedPoint.x, allowedPoint.y, readAlarmX,
? ? ? ? ? ? ? ? ? standardY) <=eventHitDistance) {
? ? ? ? ? ? ? // 命中
? ? ? ? ? ? ? alarmHitBitmap =alarmOff2OnBitmap;
? ? ? ? ? ? ? alarmOff2OnDst =readAlarmOff2OnDst;
? ? ? ? ? ? ? // 取消鎖圖標(biāo)的顯示
? ? ? ? ? ? ? lockBitmap =null;
? ? ? ? ? ? ? // 讀報(bào)警事件code,MSG_LAUNCH_READ
? ? ? ? ? ? ? eventCode =2;
? ? ? ? ? ? }else {
? ? ? ? ? ? // 沒有命中, 讀報(bào)警的圈圖標(biāo)還原
? ? ? ? ? ? ? alarmHitBitmap =null;
? ? ? ? ? ? ? // 打開鎖圖標(biāo)的顯示
? ? ? ? ? ? ? lockBitmap =lockOnBitmap;
? ? ? ? ? ? ? alarmHitBitmap =null;
? ? ? ? ? ? ? eventCode =null;
? ? ? ? ? ? }
}
// 鎖圖片被移動(dòng)的目標(biāo)位置
? ? ? ? lockRecDst = getLockOnMoveRectDst(allowedPoint);
? ? ? ? postInvalidate();
? ? ? }
}
break;
? case MotionEvent.ACTION_UP: {
// 判斷event是否命中ignore或者read區(qū)域
? ? ? // 如果命中,則進(jìn)行相應(yīng)跳轉(zhuǎn)
? ? ? if (touchDownHitFlag &&eventCode !=null) {
doTriggerEvent(eventCode);
? ? ? }else {
// 否則, 解鎖大圖復(fù)位, 并且變?yōu)槲唇怄i小圖
? ? ? ? lockBitmap =lockOffBitmap;
? ? ? ? lockRecSrc =lockOffRecSrc;
? ? ? ? lockRecDst =lockOffRecDst;
? ? ? ? // 取消命中框按鈕
? ? ? ? alarmHitBitmap =null;
? ? ? ? ?fadeInCenterLockFlag =true;
? ? ? ? postInvalidate();
? ? ? }
}
?break;
? }
return true;
}