1. 程式人生 > >一個手勢圖案解鎖的小demo

一個手勢圖案解鎖的小demo

有些應用為了安全加個圖案解鎖也不錯,下面是圖案解鎖的小demo

主要涉及到View的自定義,線、圓的繪製,以及touch事件的處理,有需要的可以參考下。

主要步驟:

1.繪製9個觸點

2.繪製連線線,觸點選中狀態

3.繪製驗證出錯時狀態

說明:

1.其中涉及的(x,y)座標都是相對於當前View的左上角(0,0)而言;

2.TextView在繪製時,是從文字的左下角開始繪製的

Touch事件處理如下:

@Override
 public boolean onTouchEvent(MotionEvent event) {
  float crtX = event.getX();//57.79834
  float crtY = event.getY();//40.588318
  
  switch (event.getAction()) {
  case MotionEvent.ACTION_DOWN:
   isUp = false;
   Log.e("--Action--Down", "--Action--Down");
   int index = getItemIndex(crtX, crtY);
   
   if(index >= 0){
    int row = index / 3;   //當前行
    int column = index % 3;//當前列
    int crtCenterX = column * (radius + padding) * 2 + padding + radius;
       int crtCenterY = row * (radius * 2 + padding * 2) + padding + radius;
    drawStartX = crtCenterX;
    drawStartY = crtCenterY;
    drawEndX = crtCenterX;
    drawEndY  = crtCenterY;
    isDrawStart = true;
   }
   
   break;
  case MotionEvent.ACTION_UP:
   isUp = true;
   Log.e("--Action--Up", "--Action--Up");
   int lineCount = lineList.size();

   if(lineCount > 0
      && !isAtPoint(lineList.get(lineCount - 1).getEndX(), lineList.get(lineCount - 1).getEndY())){
    lineList.remove(lineCount - 1);
    invalidate();
   }
   else {
    if(verifyTheKey()){
     //go to next activity
     Log.e("--go--to--next--activity--", "--go--to--next--activity--");
    }
    else {
     pointPaint.setColor(Color.RED);
     invalidate();
    }
    
    isDrawStart = false;
   }

   drawStartX= 0;
   drawStartY = 0;
   drawEndX = 0;
   drawEndY = 0;
   
   break;
  case MotionEvent.ACTION_MOVE:
   if(isDrawStart){
    int moveIndex = getItemIndex(crtX, crtY);
    
    //當前位於觸點區域
    if(moveIndex >= 0){
     int row = moveIndex / 3;   //當前行
     int column = moveIndex % 3;//當前列
     int crtCenterX = column * (radius + padding) * 2 + padding + radius;
        int crtCenterY = row * (radius * 2 + padding * 2) + padding + radius;

        if(isAtPoint(drawStartX, drawStartY)){//線的起點正在中心點上
         if(isPointContains(crtCenterX, crtCenterY)){//已經記錄過此點
          drawEndX = crtX;
          drawEndY = crtY;
          updateLines(true);
          return true;
         }
         
         if(crtX != crtCenterX || crtY != crtCenterY){//當前位置不在中心點
          drawEndX = crtCenterX;
          drawEndY = crtCenterY;
          itemList.get(moveIndex).setShowPoint(true);//顯示選中狀態
          updateLines(true);
          drawStartX = drawEndX;
          drawStartY = drawEndY;
         }
         else {//當前位置在中心點
       drawStartX = crtCenterX;
       drawStartY = crtCenterY;
       itemList.get(moveIndex).setShowPoint(true);
       updateLines(true);
      }
         
         
        }
    }
    else {//不在觸點區域
     drawEndX = crtX;
     drawEndY = crtY;
     updateLines(true);
    }
    
   }
   
   break;
  default:
   break;
  }
  
  return true;
 }

在需要重繪時呼叫invalidate方法,將導致onDraw()方法的執行,從而重新進行View的繪製。view繪製是從裡由外而進行繪製的,因而需要設定好繪製的先後順序。

主要繪製就在onDraw()方法中:

@Override
 protected void onDraw(Canvas canvas) {
  super.onDraw(canvas);
        //繪製觸點
        drawItem(canvas);
       
        //繪製連線線
        for(LineItem line : lineList){
         canvas.drawLine(line.getStartX(), line.getStartY(),
                                    line.getEndX(), line.getEndY(), linePaint);
  }
  
  if(isUp){
   if(isDrawStart){
    if(verifyTheKey()){
     //go to next activity
     Log.e("--go--to--next--activity--", "--go--to--next--activity--");
       }
       else {
     pointPaint.setColor(Color.RED);//驗證未通過,將觸點置為紅色
     invalidate();
     isDrawStart = false;
    }
   }
  }
 }

具體的demo,見: