当前位置: 移动技术网 > 移动技术>移动开发>Android > 轻松实现Android自定义九宫格图案解锁

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

2019年07月24日  | 移动技术网移动技术  | 我要评论
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("请绘制图案"); 
  } 
 } 
} 

 效果图如下:

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

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

如您对本文有疑问或者有任何想说的,请点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网