Android自定义手势密码锁

/**

* 自定义锁屏View

*/

public class  GestureLockViewextends View{

/**解锁密码key*/

  private Stringkey="";

  private OnGestureFinishListeneronGestureFinishListener;

  /**解锁圆点数组*/

  private LockCircle[]cycles;

  /**存储触碰圆的序列*/

  private ListlinedCycles =new ArrayList();

  //画笔

  /**空心外圆*/

  private PaintpaintNormal;

  /**点击后内部圆*/

  private PaintpaintInnerCycle;

  /**画路径*/

  private PaintpaintLines;

  private PathlinePath =new Path();

  /**当前手指X,Y位置*/

  private int eventX, eventY;

  /**能否操控界面绘画*/

  private boolean canContinue =true;

  /**验证结果*/

  private boolean result;

  private Timertimer;

  /**未选中颜色*/

  private final int NORMAL_COLOR = Color.parseColor("#4a76fb");

  /**错误颜色*/

  private final int ERROE_COLOR = Color.parseColor("#4a76fb"); // 正常外圆颜色

  /**选中时颜色*/

  private final int TOUCH_COLOR = Color.parseColor("#409DE5"); // 选中内圆颜色

  /**设置圈圈的数量限制*/

  private int limitNum=4;

  //=================================start=构造方法========================

  public GestureLockView(Context context, AttributeSet attrs, int defStyle) {

super(context, attrs, defStyle);

      init();

  }

public GestureLockView(Context context, AttributeSet attrs) {

this(context, attrs,0);

  }

public GestureLockView(Context context) {

this(context,null);

  }

//===============================end=构造方法========================

  /**初始化*/

  public void init()

{

paintNormal =new Paint();

      paintNormal.setAntiAlias(true);

      paintNormal.setStrokeWidth(5);

      paintNormal.setStyle(Paint.Style.STROKE);

      paintInnerCycle=new Paint();

      paintInnerCycle.setAntiAlias(true);

      paintInnerCycle.setStyle(Paint.Style.FILL);

      paintLines =new Paint();

      paintLines.setAntiAlias(true);

      paintLines.setStyle(Paint.Style.STROKE);

      paintLines.setStrokeWidth(10);

  }

@Override

  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

int specMode=MeasureSpec.getMode(widthMeasureSpec);

      int spceSize=MeasureSpec.getSize(widthMeasureSpec);

      heightMeasureSpec=MeasureSpec.makeMeasureSpec((int) (spceSize*0.85+0.5f), specMode);

      super.onMeasure(widthMeasureSpec,heightMeasureSpec);

  }

@Override

  protected void onLayout(boolean changed, int left, int top, int right,

        int bottom) {

super.onLayout(changed, left, top, right, bottom);

      int perWidthSize= getWidth() /7;

      int perHeightSize=getHeight()/6;

      /**初始化圆的参数*/

      if(cycles==null&&(perWidthSize>0)&&(perHeightSize>0)){

cycles=new LockCircle[9];

        for(int i=0;i<3;i++){

for(int j=0;j<3;j++)

{

LockCircle lockCircle=new LockCircle();

              lockCircle.setNum(i*3+j);

              lockCircle.setOx(perWidthSize*(j*2+1.5f)+0.5f);

              lockCircle.setOy(perHeightSize*(i*2+1)+0.5f);

              lockCircle.setR(perWidthSize*0.6f);

              cycles[i*3+j]=lockCircle;

            }

}

}

}

/**

    * 设置手势密码连接的数量值

    * @param limitNum

    */

  public void setLimitNum(int limitNum){

this.limitNum=limitNum;

  }

/**

    * 设置key值留验证用,要是没有设置就代表是设置手势密码

    * @param key

    */

  public void setKey(String key){

this.key=key;

  }

public void setOnGestureFinishListener(OnGestureFinishListener onGestureFinishListener) {

this.onGestureFinishListener = onGestureFinishListener;

  }

/**手势输入完成后回调接口*/

  public interface OnGestureFinishListener

{

/**手势输入完成后回调函数*/

      public void OnGestureFinish(boolean success, String key);

  }

/**监听手势*/

  @Override

  public boolean onTouchEvent(MotionEvent event) {

if(canContinue){

switch(event.getAction()){

case MotionEvent.ACTION_DOWN:

case MotionEvent.ACTION_MOVE:

eventX=(int) event.getX();

            eventY=(int) event.getY();

            for(int i=0;i

if(cycles[i].isPointIn(eventX, eventY)){

cycles[i].setOnTouch(true);

                  if(!linedCycles.contains(cycles[i].getNum())){

linedCycles.add(cycles[i].getNum());

                  }

}

}

break;

        case MotionEvent.ACTION_UP:

//手指离开暂停触碰

            canContinue=false;

            StringBuffer stringBuffer=new StringBuffer();

            for(int i=0;i

stringBuffer.append(linedCycles.get(i)+1);

            }

if(!TextUtils.isEmpty(key))

result=key.equals(stringBuffer.toString());

else

              result=true;

            if(linedCycles.size()

result=false;

            }

if(onGestureFinishListener!=null&&linedCycles.size()>0){

onGestureFinishListener.OnGestureFinish(result, stringBuffer.toString());

            }

timer=new Timer();

            timer.schedule(new TimerTask() {

@Override

              public void run() {

eventX =eventY =0;

                  for(int i=0;i<9;i++)

{

cycles[i].setOnTouch(false);

                  }

linedCycles.clear();

                  linePath.reset();

                  canContinue =true;

                  postInvalidate();//在非ui线程刷新界面

              }

}, 1000);

break;

        }

invalidate();

      }

return true;

  }

@Override

  protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

      int cycleSize =cycles.length;

      for (int i =0; i < cycleSize; i++) {

// 画完并且错误

        if (!canContinue && !result)

{

if (cycles[i].isOnTouch()) {

drawInnerCycle(cycles[i], canvas, ERROE_COLOR);

              drawOutsideCycle(cycles[i], canvas, ERROE_COLOR);

            }else

              drawOutsideCycle(cycles[i], canvas, NORMAL_COLOR);

        }

//绘画中

        else {

if (cycles[i].isOnTouch()) {

drawInnerCycle(cycles[i], canvas, TOUCH_COLOR);

              drawOutsideCycle(cycles[i], canvas, TOUCH_COLOR);

            }else

              drawOutsideCycle(cycles[i], canvas, NORMAL_COLOR);

        }

}

if (!canContinue && !result) {

drawLine(canvas, ERROE_COLOR);

      }else {

drawLine(canvas, TOUCH_COLOR);

      }

}

/**画空心圆*/

  private void drawOutsideCycle(LockCircle lockCircle, Canvas canvas,int color)

{

paintNormal.setColor(color);

      canvas.drawCircle(lockCircle.getOx(), lockCircle.getOy(),

            lockCircle.getR(), paintNormal);

  }

/**画横线*/

  private void drawLine(Canvas canvas,int color)

{

//构建路径

      linePath.reset();

      if (linedCycles.size() >0) {

int size=linedCycles.size();

        for (int i =0; i < size; i++) {

int index =linedCycles.get(i);

            float x =cycles[index].getOx();

            float y =cycles[index].getOy();

            if (i ==0) {

linePath.moveTo(x,y);

            }else {

linePath.lineTo(x,y);

            }

}

if (canContinue) {

linePath.lineTo(eventX, eventY);

        }else {

linePath.lineTo(cycles[linedCycles.get(linedCycles.size()-1)].getOx(), cycles[linedCycles.get(linedCycles.size()-1)].getOy());

        }

paintLines.setColor(color);

        canvas.drawPath(linePath, paintLines);

      }

}

/**画中心圆圆*/

  private void drawInnerCycle(LockCircle myCycle, Canvas canvas,int color) {

paintInnerCycle.setColor(color);

      canvas.drawCircle(myCycle.getOx(), myCycle.getOy(), myCycle.getR() /3f,

            paintInnerCycle);

  }

/**

    * 每个圆点类

    *

    * @author rxx

*

    * 2014年12月12日  上午10:05:48

*/

  class LockCircle {

/**圆心横坐标*/

      private float ox;

      /**圆心纵坐标*/

      private float oy;

      /**半径长度*/

      private float r;

      /**代表数值*/

      private Integernum;

      /**是否选择:false=未选中*/

      private boolean onTouch;

      public float getOx() {

return ox;

      }

public void setOx(float ox) {

this.ox = ox;

      }

public float getOy() {

return oy;

      }

public void setOy(float oy) {

this.oy = oy;

      }

public void setOy(int oy) {

this.oy = oy;

      }

public float getR() {

return r;

      }

public void setR(float r) {

this.r = r;

      }

public IntegergetNum() {

return num;

      }

public void setNum(Integer num) {

this.num = num;

      }

public boolean isOnTouch() {

return onTouch;

      }

public void setOnTouch(boolean onTouch) {

this.onTouch = onTouch;

      }

/**判读传入位置是否在圆心内部*/

      public boolean isPointIn(int x, int y) {

double distance = Math.sqrt((x -ox) * (x -ox) + (y -oy) * (y -oy));

        return distance

      }

}

}

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容