欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

轻松实现Android自定义九宫格图案解锁

程序员文章站 2024-03-01 20:12:10
android实现九宫格图案解锁,自带将图案转化成数字密码的功能,代码如下: lockpatternview.java package com.jackie.l...

android实现九宫格图案解锁,自带将图案转化成数字密码的功能,代码如下:

lockpatternview.java

package com.jackie.lockpattern; 
 
import android.content.context; 
import android.graphics.canvas; 
import android.graphics.paint; 
import android.graphics.point; 
import android.text.textutils; 
import android.util.attributeset; 
import android.util.typedvalue; 
import android.view.motionevent; 
import android.view.view; 
 
import java.util.arraylist; 
import java.util.list; 
 
/** 
 * created by jackie on 2015/12/24. 
 * 图案解锁 
 */ 
public class lockpatternview extends view { 
 /** 
  * 圆的画笔 
  */ 
 private paint mcirclepaint; 
 /** 
  * 线的画笔 
  */ 
 private paint mlinepaint; 
 /** 
  * 圆心数组 
  */ 
 private pointview[][] mpointviewarray = new pointview[3][3]; 
 /** 
  * 保存选中点的集合 
  */ 
 private list<pointview> mselectedpointviewlist; 
 
 
 /** 
  * 解锁图案的边长 
  */ 
 private int mpatternwidth; 
 
 /** 
  * 图案监听器 
  */ 
 private onpatternchangelistener monpatternchangelistener; 
 
 /** 
  * 半径 
  */ 
 private float mradius; 
 
 /** 
  * 每个圆圈的下标 
  */ 
 private int mindex = 1; 
 
 /** 
  * 第一个点是否选中 
  */ 
 private boolean misselected; 
 /** 
  * 是否绘制结束 
  */ 
 private boolean misfinished; 
 
 /** 
  * 正在滑动并且没有任何点选中 
  */ 
 private boolean mismovingwithoutcircle = false; 
 
 private float mcurrentx, mcurrenty; 
 
 /** 
  * 正常状态的颜色 
  */ 
 private static final int normal_color = 0xff70dbdb; 
 /** 
  * 选中状态的颜色 
  */ 
 private static final int selected_color = 0xff979797; 
 
 public lockpatternview(context context) { 
  this(context, null); 
 } 
 
 public lockpatternview(context context, attributeset attrs) { 
  super(context, attrs); 
 
  mcirclepaint = new paint(); 
  mcirclepaint.setantialias(true); 
  mcirclepaint.setdither(true); 
  mcirclepaint.setcolor(normal_color); 
  mcirclepaint.setstyle(paint.style.fill); 
 
  mlinepaint = new paint(); 
  mlinepaint.setantialias(true); 
  mlinepaint.setdither(true); 
  mlinepaint.setstrokewidth(20); 
  mlinepaint.setcolor(selected_color); 
  mlinepaint.setstyle(paint.style.stroke); 
 
  mradius = typedvalue.applydimension(typedvalue.complex_unit_dip, 20, getresources().getdisplaymetrics()); 
 
  mselectedpointviewlist = new arraylist<>(); 
 } 
 
 @override 
 protected void onmeasure(int widthmeasurespec, int heightmeasurespec) { 
  super.onmeasure(widthmeasurespec, heightmeasurespec); 
 
  //取屏幕长和宽中的较小值作为图案的边长 
  mpatternwidth = math.min(getmeasuredwidth(), getmeasuredheight()); 
  setmeasureddimension(mpatternwidth, mpatternwidth); 
 } 
 
 @override 
 protected void ondraw(canvas canvas) { 
  //画圆 
  drawcircle(canvas); 
 
  //将选中的圆重新绘制一遍,将选中的点和未选中的点区别开来 
  for (pointview pointview : mselectedpointviewlist) { 
   mcirclepaint.setcolor(selected_color); 
   canvas.drawcircle(pointview.x, pointview.y, mradius, mcirclepaint); 
   mcirclepaint.setcolor(normal_color); //每重新绘制一个,将画笔的颜色重置,保证不会影响其他圆的绘制 
  } 
 
  //点与点画线 
  if (mselectedpointviewlist.size() > 0) { 
   point pointviewa = mselectedpointviewlist.get(0); //第一个选中的点为a点 
   for (int i = 0; i < mselectedpointviewlist.size(); i++) { 
    point pointviewb = mselectedpointviewlist.get(i); //其他依次遍历出来的点为b点 
    drawline(canvas, pointviewa, pointviewb); 
    pointviewa = pointviewb; 
   } 
 
   //点与鼠标当前位置绘制轨迹 
   if (mismovingwithoutcircle & !misfinished) { 
    drawline(canvas, pointviewa, new pointview((int)mcurrentx, (int)mcurrenty)); 
   } 
  } 
 
  super.ondraw(canvas); 
 } 
 
 /** 
  * 画圆 
  * @param canvas 画布 
  */ 
 private void drawcircle(canvas canvas) { 
  //初始化点的位置 
  for (int i = 0; i < mpointviewarray.length; i++) { 
   for (int j = 0; j < mpointviewarray.length; j++) { 
    //圆心的坐标 
    int cx = mpatternwidth / 4 * (j + 1); 
    int cy = mpatternwidth / 4 * (i + 1); 
 
    //将圆心放在一个点数组中 
    pointview pointview = new pointview(cx, cy); 
    pointview.setindex(mindex); 
    mpointviewarray[i][j] = pointview; 
    canvas.drawcircle(cx, cy, mradius, mcirclepaint); 
    mindex++; 
   } 
  } 
 
  mindex = 1; 
 } 
 
 /** 
  * 画线 
  * @param canvas 画布 
  * @param pointa 第一个点 
  * @param pointb 第二个点 
  */ 
 private void drawline(canvas canvas, point pointa, point pointb) { 
  canvas.drawline(pointa.x, pointa.y, pointb.x, pointb.y, mlinepaint); 
 } 
 
 @override 
 public boolean ontouchevent(motionevent event) { 
  mcurrentx = event.getx(); 
  mcurrenty = event.gety(); 
  pointview selectedpointview = null; 
 
  switch(event.getaction()) { 
   case motionevent.action_down: 
    //重新绘制 
    if (monpatternchangelistener != null) { 
     monpatternchangelistener.onpatternstarted(true); 
    } 
 
    mselectedpointviewlist.clear(); 
    misfinished = false; 
 
    selectedpointview = checkselectpoint(); 
 
    if (selectedpointview != null) { 
     //第一次按下的位置在圆内,被选中 
     misselected = true; 
    } 
    break; 
   case motionevent.action_move: 
    if (misselected) { 
     selectedpointview = checkselectpoint(); 
    } 
 
    if (selectedpointview == null) { 
     mismovingwithoutcircle = true; 
    } 
    break; 
   case motionevent.action_up: 
    misfinished = true; 
    misselected = false; 
    break; 
  } 
 
  //将选中的点收集起来 
  if (!misfinished && misselected && selectedpointview != null) { 
   if (!mselectedpointviewlist.contains(selectedpointview)) { 
    mselectedpointviewlist.add(selectedpointview); 
   } 
  } 
 
  if (misfinished) { 
   if (mselectedpointviewlist.size() == 1) { 
    mselectedpointviewlist.clear(); 
   } else if (mselectedpointviewlist.size() < 5 && mselectedpointviewlist.size() > 0) { 
    //绘制错误 
    if (monpatternchangelistener != null) { 
     monpatternchangelistener.onpatternchange(null); 
    } 
   } else { 
    //绘制成功 
    string patternpassword = ""; 
    if (monpatternchangelistener != null) { 
     for (pointview pointview : mselectedpointviewlist) { 
      patternpassword += pointview.getindex(); 
     } 
 
     if (!textutils.isempty(patternpassword)) { 
      monpatternchangelistener.onpatternchange(patternpassword); 
     } 
    } 
   } 
  } 
 
  invalidate(); 
  return true; 
 } 
 
 /** 
  * 判断当前按下的位置是否在圆心数组中 
  * @return 返回选中的点 
  */ 
 private pointview checkselectpoint() { 
  for (int i = 0; i < mpointviewarray.length; i++) { 
   for (int j = 0; j < mpointviewarray.length; j++) { 
    pointview pointview = mpointviewarray[i][j]; 
    if (iswithincircle(mcurrentx, mcurrenty, pointview.x, pointview.y, mradius)) { 
     return pointview; 
    } 
   } 
  } 
 
  return null; 
 } 
 
 /** 
  * 判断点是否在圆内 
  * @param x  点x轴坐标 
  * @param y  点y轴坐标 
  * @param cx  圆心x坐标 
  * @param cy  圆心y坐标 
  * @param radius 半径 
  * @return  true表示在圆内,false表示在圆外 
  */ 
 private boolean iswithincircle(float x, float y, float cx, float cy, float radius) { 
  //如果点和圆心的距离小于半径,则证明点在圆内 
  if (math.sqrt(math.pow(x - cx, 2) + math.pow(y- cy, 2)) <= radius) { 
   return true; 
  } 
 
  return false; 
 } 
 
 /** 
  * 设置图案监听器 
  */ 
 public void setonpatternchangelistener(onpatternchangelistener onpatternchangelistener) { 
  if (onpatternchangelistener != null) { 
   this.monpatternchangelistener = onpatternchangelistener; 
  } 
 } 
 
 /** 
  * 图案监听器 
  */ 
 public interface onpatternchangelistener { 
  /** 
   * 图案改变 
   * @param patternpassword 图案密码 
   */ 
  void onpatternchange(string patternpassword); 
 
  /** 
   * 图案是否重新绘制 
   * @param isstarted 重新绘制 
   */ 
  void onpatternstarted(boolean isstarted); 
 } 
} 

pointview.java

package com.jackie.lockpattern; 
 
import android.graphics.point; 
 
/** 
 * created by jackie on 2015/12/25. 
 * 自定义点对象 
 */ 
public class pointview extends point { 
 //用于转化密码的下标 
 public int index; 
 
 public pointview(int x, int y) { 
  super(x, y); 
 } 
 
 public int getindex() { 
  return index; 
 } 
 
 public void setindex(int index) { 
  this.index = index; 
 } 
} 

mainactivity.java

package com.jackie.lockpattern; 
 
import android.app.activity; 
import android.os.bundle; 
import android.widget.textview; 
 
public class mainactivity extends activity implements lockpatternview.onpatternchangelistener { 
 private textview mlockpatternhint; 
 private lockpatternview mlockpatternview; 
 
 @override 
 protected void oncreate(bundle savedinstancestate) { 
  super.oncreate(savedinstancestate); 
  setcontentview(r.layout.activity_main); 
 
  mlockpatternhint = (textview) findviewbyid(r.id.lock_pattern_hint); 
  mlockpatternview = (lockpatternview) findviewbyid(r.id.lock_pattern_view); 
  mlockpatternview.setonpatternchangelistener(this); 
 
 } 
 
 @override 
 public void onpatternchange(string patternpassword) { 
  if (patternpassword == null) { 
   mlockpatternhint.settext("至少5个点"); 
  } else { 
   mlockpatternhint.settext(patternpassword); 
  } 
 } 
 
 @override 
 public void onpatternstarted(boolean isstarted) { 
  if (isstarted) { 
   mlockpatternhint.settext("请绘制图案"); 
  } 
 } 
} 

 效果图如下:

轻松实现Android自定义九宫格图案解锁

轻松实现Android自定义九宫格图案解锁

附上源码地址:https://github.com/shineflower/lockpattern.git

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。