Android自定義view 鎖屏的繪制

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;

}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容