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

超实用的Android手势锁制作实例教程

程序员文章站 2024-03-01 21:43:04
今天偶遇以github上gesturelock关于手势锁的一个例子(有兴趣的去搜索下看看),于是下载下来研究,无奈基本没有注释,代码上存在一些问题(当设置gravity=c...

今天偶遇以github上gesturelock关于手势锁的一个例子(有兴趣的去搜索下看看),于是下载下来研究,无奈基本没有注释,代码上存在一些问题(当设置gravity=center_vertical无法进行手势选择,无意中发现的),于是借鉴这位仁兄的代码,自己重写写了一个,修复了一些问题,加入一些基本的自定义属性,在此先感谢这位兄弟~。
先上图,默认效果图:

超实用的Android手势锁制作实例教程

当然可以自定义数量啊,颜色神马的,自定义效果图:

超实用的Android手势锁制作实例教程

超实用的Android手势锁制作实例教程

如果你有艺术细胞,可以给我推荐几个颜色,无奈个人审美有问题~

1、整体思路
a、自定义了一个relativelayout(gesturelockviewgroup)在里面会根据传入的每行的个数,生成多个gesturelockview(就是上面一个个小圈圈),然后会自动进行布局,里面的宽度,间距,内圆的直径,箭头的大小神马的都是百分比实现的,所以大胆的设置你喜欢的个数,只要你没有密集恐惧症~
b、gesturelockview有三个状态,没有手指触碰、手指触碰、和手指抬起,会根据这三个状态绘制不同的效果,以及抬起时的小箭头需要旋转的角度,会根据用户选择的gesturelockview,进行计算,在gesturelockviewgroup为每个gesturelockview设置
c、gesturelockviewgroup主要就是判断用户action_move,action_down , action_up时改变选中的gesturelockview的状态,并且记录下来,提供一定的回调。
下面开始看代码:

2、声明一些用户可以设置的属性:

<?xml version="1.0" encoding="utf-8"?> 
<resources> 
 
  <attr name="color_no_finger_inner_circle" format="color" /> 
  <attr name="color_no_finger_outer_circle" format="color" /> 
  <attr name="color_finger_on" format="color" /> 
  <attr name="color_finger_up" format="color" /> 
  <attr name="count" format="integer" /> 
  <attr name="trytimes" format="integer" /> 
 
  <declare-styleable name="gesturelockviewgroup"> 
    <attr name="color_no_finger_inner_circle" /> 
    <attr name="color_no_finger_outer_circle" /> 
    <attr name="color_finger_on" /> 
    <attr name="color_finger_up" /> 
    <attr name="count" /> 
    <attr name="trytimes" /> 
  </declare-styleable> 
 
</resources> 

用户可以用过在xml文件中设置这些属性,改变外观,最多尝试次数以及数量等。

3、gesturelockview

package com.zhy.zhy_gesturelockview.view; 
 
import android.content.context; 
import android.graphics.canvas; 
import android.graphics.paint; 
import android.graphics.paint.style; 
import android.graphics.path; 
import android.view.view; 
 
public class gesturelockview extends view 
{ 
  private static final string tag = "gesturelockview"; 
  /** 
   * gesturelockview的三种状态 
   */ 
  enum mode 
  { 
    status_no_finger, status_finger_on, status_finger_up; 
  } 
 
  /** 
   * gesturelockview的当前状态 
   */ 
  private mode mcurrentstatus = mode.status_no_finger; 
   
  /** 
   * 宽度 
   */ 
  private int mwidth; 
  /** 
   * 高度 
   */ 
  private int mheight; 
  /** 
   * 外圆半径 
   */ 
  private int mradius; 
  /** 
   * 画笔的宽度 
   */ 
  private int mstrokewidth = 2; 
 
  /** 
   * 圆心坐标 
   */ 
  private int mcenterx; 
  private int mcentery; 
  private paint mpaint; 
 
  /** 
   * 箭头(小三角最长边的一半长度 = marrawrate * mwidth / 2 ) 
   */ 
  private float marrowrate = 0.333f; 
  private int marrowdegree = -1; 
  private path marrowpath; 
  /** 
   * 内圆的半径 = minnercircleradiusrate * mradus 
   * 
   */ 
  private float minnercircleradiusrate = 0.3f; 
 
  /** 
   * 四个颜色,可由用户自定义,初始化时由gesturelockviewgroup传入 
   */ 
  private int mcolornofingerinner; 
  private int mcolornofingeroutter; 
  private int mcolorfingeron; 
  private int mcolorfingerup; 
 
  public gesturelockview(context context , int colornofingerinner , int colornofingeroutter , int colorfingeron , int colorfingerup ) 
  { 
    super(context); 
    this.mcolornofingerinner = colornofingerinner; 
    this.mcolornofingeroutter = colornofingeroutter; 
    this.mcolorfingeron = colorfingeron; 
    this.mcolorfingerup = colorfingerup; 
    mpaint = new paint(paint.anti_alias_flag); 
    marrowpath = new path(); 
 
  } 
 
  @override 
  protected void onmeasure(int widthmeasurespec, int heightmeasurespec) 
  { 
    super.onmeasure(widthmeasurespec, heightmeasurespec); 
 
    mwidth = measurespec.getsize(widthmeasurespec); 
    mheight = measurespec.getsize(heightmeasurespec); 
 
    // 取长和宽中的小值 
    mwidth = mwidth < mheight ? mwidth : mheight; 
    mradius = mcenterx = mcentery = mwidth / 2; 
    mradius -= mstrokewidth / 2; 
 
    // 绘制三角形,初始时是个默认箭头朝上的一个等腰三角形,用户绘制结束后,根据由两个gesturelockview决定需要旋转多少度 
    float marrowlength = mwidth / 2 * marrowrate; 
    marrowpath.moveto(mwidth / 2, mstrokewidth + 2); 
    marrowpath.lineto(mwidth / 2 - marrowlength, mstrokewidth + 2 
        + marrowlength); 
    marrowpath.lineto(mwidth / 2 + marrowlength, mstrokewidth + 2 
        + marrowlength); 
    marrowpath.close(); 
    marrowpath.setfilltype(path.filltype.winding); 
 
  } 
 
  @override 
  protected void ondraw(canvas canvas) 
  { 
 
    switch (mcurrentstatus) 
    { 
    case status_finger_on: 
 
      // 绘制外圆 
      mpaint.setstyle(style.stroke); 
      mpaint.setcolor(mcolorfingeron); 
      mpaint.setstrokewidth(2); 
      canvas.drawcircle(mcenterx, mcentery, mradius, mpaint); 
      // 绘制内圆 
      mpaint.setstyle(style.fill); 
      canvas.drawcircle(mcenterx, mcentery, mradius 
          * minnercircleradiusrate, mpaint); 
      break; 
    case status_finger_up: 
      // 绘制外圆 
      mpaint.setcolor(mcolorfingerup); 
      mpaint.setstyle(style.stroke); 
      mpaint.setstrokewidth(2); 
      canvas.drawcircle(mcenterx, mcentery, mradius, mpaint); 
      // 绘制内圆 
      mpaint.setstyle(style.fill); 
      canvas.drawcircle(mcenterx, mcentery, mradius 
          * minnercircleradiusrate, mpaint); 
 
      drawarrow(canvas); 
 
      break; 
 
    case status_no_finger: 
 
      // 绘制外圆 
      mpaint.setstyle(style.fill); 
      mpaint.setcolor(mcolornofingeroutter); 
      canvas.drawcircle(mcenterx, mcentery, mradius, mpaint); 
      // 绘制内圆 
      mpaint.setcolor(mcolornofingerinner); 
      canvas.drawcircle(mcenterx, mcentery, mradius 
          * minnercircleradiusrate, mpaint); 
      break; 
 
    } 
 
  } 
 
  /** 
   * 绘制箭头 
   * @param canvas 
   */ 
  private void drawarrow(canvas canvas) 
  { 
    if (marrowdegree != -1) 
    { 
      mpaint.setstyle(paint.style.fill); 
 
      canvas.save(); 
      canvas.rotate(marrowdegree, mcenterx, mcentery); 
      canvas.drawpath(marrowpath, mpaint); 
 
      canvas.restore(); 
    } 
 
  } 
 
  /** 
   * 设置当前模式并重绘界面 
   * 
   * @param mode 
   */ 
  public void setmode(mode mode) 
  { 
    this.mcurrentstatus = mode; 
    invalidate(); 
  } 
 
  public void setarrowdegree(int degree) 
  { 
    this.marrowdegree = degree; 
  } 
 
  public int getarrowdegree() 
  { 
    return this.marrowdegree; 
  } 
} 

注释很详细,主要就是ondraw时,判断当前状态,绘制不同的显示效果;状态的改变都是gesturelockviewgroup的ontouchevent中设置的。

4、gesturelockviewgroup

package com.zhy.zhy_gesturelockview.view; 
 
import java.util.arraylist; 
import java.util.list; 
 
import android.content.context; 
import android.content.res.typedarray; 
import android.graphics.canvas; 
import android.graphics.color; 
import android.graphics.paint; 
import android.graphics.path; 
import android.graphics.point; 
import android.util.attributeset; 
import android.util.log; 
import android.view.motionevent; 
import android.view.view; 
import android.widget.relativelayout; 
 
import com.zhy.zhy_gesturelockview.r; 
import com.zhy.zhy_gesturelockview.view.gesturelockview.mode; 
 
/** 
 * 整体包含n*n个gesturelockview,每个gesturelockview间间隔mmarginbetweenlockview, 
 * 最外层的gesturelockview与容器存在mmarginbetweenlockview的外边距 
 * 
 * 关于gesturelockview的边长(n*n): n * mgesturelockviewwidth + ( n + 1 ) * 
 * mmarginbetweenlockview = mwidth ; 得:mgesturelockviewwidth = 4 * mwidth / ( 5 
 * * mcount + 1 ) 注:mmarginbetweenlockview = mgesturelockviewwidth * 0.25 ; 
 * 
 * @author zhy 
 * 
 */ 
public class gesturelockviewgroup extends relativelayout 
{ 
 
  private static final string tag = "gesturelockviewgroup"; 
  /** 
   * 保存所有的gesturelockview 
   */ 
  private gesturelockview[] mgesturelockviews; 
  /** 
   * 每个边上的gesturelockview的个数 
   */ 
  private int mcount = 4; 
  /** 
   * 存储答案 
   */ 
  private int[] manswer = { 0, 1, 2, 5, 8 }; 
  /** 
   * 保存用户选中的gesturelockview的id 
   */ 
  private list<integer> mchoose = new arraylist<integer>(); 
 
  private paint mpaint; 
  /** 
   * 每个gesturelockview中间的间距 设置为:mgesturelockviewwidth * 25% 
   */ 
  private int mmarginbetweenlockview = 30; 
  /** 
   * gesturelockview的边长 4 * mwidth / ( 5 * mcount + 1 ) 
   */ 
  private int mgesturelockviewwidth; 
 
  /** 
   * gesturelockview无手指触摸的状态下内圆的颜色 
   */ 
  private int mnofingerinnercirclecolor = 0xff939090; 
  /** 
   * gesturelockview无手指触摸的状态下外圆的颜色 
   */ 
  private int mnofingeroutercirclecolor = 0xffe0dbdb; 
  /** 
   * gesturelockview手指触摸的状态下内圆和外圆的颜色 
   */ 
  private int mfingeroncolor = 0xff378fc9; 
  /** 
   * gesturelockview手指抬起的状态下内圆和外圆的颜色 
   */ 
  private int mfingerupcolor = 0xffff0000; 
 
  /** 
   * 宽度 
   */ 
  private int mwidth; 
  /** 
   * 高度 
   */ 
  private int mheight; 
 
  private path mpath; 
  /** 
   * 指引线的开始位置x 
   */ 
  private int mlastpathx; 
  /** 
   * 指引线的开始位置y 
   */ 
  private int mlastpathy; 
  /** 
   * 指引下的结束位置 
   */ 
  private point mtmptarget = new point(); 
 
  /** 
   * 最大尝试次数 
   */ 
  private int mtrytimes = 4; 
  /** 
   * 回调接口 
   */ 
  private ongesturelockviewlistener mongesturelockviewlistener; 
 
  public gesturelockviewgroup(context context, attributeset attrs) 
  { 
    this(context, attrs, 0); 
  } 
 
  public gesturelockviewgroup(context context, attributeset attrs, 
      int defstyle) 
  { 
    super(context, attrs, defstyle); 
    /** 
     * 获得所有自定义的参数的值 
     */ 
    typedarray a = context.gettheme().obtainstyledattributes(attrs, 
        r.styleable.gesturelockviewgroup, defstyle, 0); 
    int n = a.getindexcount(); 
 
    for (int i = 0; i < n; i++) 
    { 
      int attr = a.getindex(i); 
      switch (attr) 
      { 
      case r.styleable.gesturelockviewgroup_color_no_finger_inner_circle: 
        mnofingerinnercirclecolor = a.getcolor(attr, 
            mnofingerinnercirclecolor); 
        break; 
      case r.styleable.gesturelockviewgroup_color_no_finger_outer_circle: 
        mnofingeroutercirclecolor = a.getcolor(attr, 
            mnofingeroutercirclecolor); 
        break; 
      case r.styleable.gesturelockviewgroup_color_finger_on: 
        mfingeroncolor = a.getcolor(attr, mfingeroncolor); 
        break; 
      case r.styleable.gesturelockviewgroup_color_finger_up: 
        mfingerupcolor = a.getcolor(attr, mfingerupcolor); 
        break; 
      case r.styleable.gesturelockviewgroup_count: 
        mcount = a.getint(attr, 3); 
        break; 
      case r.styleable.gesturelockviewgroup_trytimes: 
        mtrytimes = a.getint(attr, 5); 
      default: 
        break; 
      } 
    } 
 
    a.recycle(); 
 
    // 初始化画笔 
    mpaint = new paint(paint.anti_alias_flag); 
    mpaint.setstyle(paint.style.stroke); 
    // mpaint.setstrokewidth(20); 
    mpaint.setstrokecap(paint.cap.round); 
    mpaint.setstrokejoin(paint.join.round); 
    // mpaint.setcolor(color.parsecolor("#aaffffff")); 
    mpath = new path(); 
  } 
 
  @override 
  protected void onmeasure(int widthmeasurespec, int heightmeasurespec) 
  { 
    super.onmeasure(widthmeasurespec, heightmeasurespec); 
 
    mwidth = measurespec.getsize(widthmeasurespec); 
    mheight = measurespec.getsize(heightmeasurespec); 
 
    // log.e(tag, mwidth + ""); 
    // log.e(tag, mheight + ""); 
 
    mheight = mwidth = mwidth < mheight ? mwidth : mheight; 
 
    // setmeasureddimension(mwidth, mheight); 
 
    // 初始化mgesturelockviews 
    if (mgesturelockviews == null) 
    { 
      mgesturelockviews = new gesturelockview[mcount * mcount]; 
      // 计算每个gesturelockview的宽度 
      mgesturelockviewwidth = (int) (4 * mwidth * 1.0f / (5 * mcount + 1)); 
      //计算每个gesturelockview的间距 
      mmarginbetweenlockview = (int) (mgesturelockviewwidth * 0.25); 
      // 设置画笔的宽度为gesturelockview的内圆直径稍微小点(不喜欢的话,随便设) 
      mpaint.setstrokewidth(mgesturelockviewwidth * 0.29f); 
 
      for (int i = 0; i < mgesturelockviews.length; i++) 
      { 
        //初始化每个gesturelockview 
        mgesturelockviews[i] = new gesturelockview(getcontext(), 
            mnofingerinnercirclecolor, mnofingeroutercirclecolor, 
            mfingeroncolor, mfingerupcolor); 
        mgesturelockviews[i].setid(i + 1); 
        //设置参数,主要是定位gesturelockview间的位置 
        relativelayout.layoutparams lockerparams = new relativelayout.layoutparams( 
            mgesturelockviewwidth, mgesturelockviewwidth); 
 
        // 不是每行的第一个,则设置位置为前一个的右边 
        if (i % mcount != 0) 
        { 
          lockerparams.addrule(relativelayout.right_of, 
              mgesturelockviews[i - 1].getid()); 
        } 
        // 从第二行开始,设置为上一行同一位置view的下面 
        if (i > mcount - 1) 
        { 
          lockerparams.addrule(relativelayout.below, 
              mgesturelockviews[i - mcount].getid()); 
        } 
        //设置右下左上的边距 
        int rightmargin = mmarginbetweenlockview; 
        int bottommargin = mmarginbetweenlockview; 
        int leftmagin = 0; 
        int topmargin = 0; 
        /** 
         * 每个view都有右外边距和底外边距 第一行的有上外边距 第一列的有左外边距 
         */ 
        if (i >= 0 && i < mcount)// 第一行 
        { 
          topmargin = mmarginbetweenlockview; 
        } 
        if (i % mcount == 0)// 第一列 
        { 
          leftmagin = mmarginbetweenlockview; 
        } 
 
        lockerparams.setmargins(leftmagin, topmargin, rightmargin, 
            bottommargin); 
        mgesturelockviews[i].setmode(mode.status_no_finger); 
        addview(mgesturelockviews[i], lockerparams); 
      } 
 
      log.e(tag, "mwidth = " + mwidth + " , mgestureviewwidth = " 
          + mgesturelockviewwidth + " , mmarginbetweenlockview = " 
          + mmarginbetweenlockview); 
 
    } 
  } 
 
  @override 
  public boolean ontouchevent(motionevent event) 
  { 
    int action = event.getaction(); 
    int x = (int) event.getx(); 
    int y = (int) event.gety(); 
 
    switch (action) 
    { 
    case motionevent.action_down: 
      // 重置 
      reset(); 
      break; 
    case motionevent.action_move: 
      mpaint.setcolor(mfingeroncolor); 
      mpaint.setalpha(50); 
      gesturelockview child = getchildidbypos(x, y); 
      if (child != null) 
      { 
        int cid = child.getid(); 
        if (!mchoose.contains(cid)) 
        { 
          mchoose.add(cid); 
          child.setmode(mode.status_finger_on); 
          if (mongesturelockviewlistener != null) 
            mongesturelockviewlistener.onblockselected(cid); 
          // 设置指引线的起点 
          mlastpathx = child.getleft() / 2 + child.getright() / 2; 
          mlastpathy = child.gettop() / 2 + child.getbottom() / 2; 
 
          if (mchoose.size() == 1)// 当前添加为第一个 
          { 
            mpath.moveto(mlastpathx, mlastpathy); 
          } else 
          // 非第一个,将两者使用线连上 
          { 
            mpath.lineto(mlastpathx, mlastpathy); 
          } 
 
        } 
      } 
      // 指引线的终点 
      mtmptarget.x = x; 
      mtmptarget.y = y; 
      break; 
    case motionevent.action_up: 
 
      mpaint.setcolor(mfingerupcolor); 
      mpaint.setalpha(50); 
      this.mtrytimes--; 
 
      // 回调是否成功 
      if (mongesturelockviewlistener != null && mchoose.size() > 0) 
      { 
        mongesturelockviewlistener.ongestureevent(checkanswer()); 
        if (this.mtrytimes == 0) 
        { 
          mongesturelockviewlistener.onunmatchedexceedboundary(); 
        } 
      } 
 
      log.e(tag, "munmatchexceedboundary = " + mtrytimes); 
      log.e(tag, "mchoose = " + mchoose); 
      // 将终点设置位置为起点,即取消指引线 
      mtmptarget.x = mlastpathx; 
      mtmptarget.y = mlastpathy; 
 
      // 改变子元素的状态为up 
      changeitemmode(); 
       
      // 计算每个元素中箭头需要旋转的角度 
      for (int i = 0; i + 1 < mchoose.size(); i++) 
      { 
        int childid = mchoose.get(i); 
        int nextchildid = mchoose.get(i + 1); 
 
        gesturelockview startchild = (gesturelockview) findviewbyid(childid); 
        gesturelockview nextchild = (gesturelockview) findviewbyid(nextchildid); 
 
        int dx = nextchild.getleft() - startchild.getleft(); 
        int dy = nextchild.gettop() - startchild.gettop(); 
        // 计算角度 
        int angle = (int) math.todegrees(math.atan2(dy, dx)) + 90; 
        startchild.setarrowdegree(angle); 
      } 
      break; 
 
    } 
    invalidate(); 
    return true; 
  } 
 
  private void changeitemmode() 
  { 
    for (gesturelockview gesturelockview : mgesturelockviews) 
    { 
      if (mchoose.contains(gesturelockview.getid())) 
      { 
        gesturelockview.setmode(mode.status_finger_up); 
      } 
    } 
  } 
 
  /** 
   * 
   * 做一些必要的重置 
   */ 
  private void reset() 
  { 
    mchoose.clear(); 
    mpath.reset(); 
    for (gesturelockview gesturelockview : mgesturelockviews) 
    { 
      gesturelockview.setmode(mode.status_no_finger); 
      gesturelockview.setarrowdegree(-1); 
    } 
  } 
  /** 
   * 检查用户绘制的手势是否正确 
   * @return 
   */ 
  private boolean checkanswer() 
  { 
    if (manswer.length != mchoose.size()) 
      return false; 
 
    for (int i = 0; i < manswer.length; i++) 
    { 
      if (manswer[i] != mchoose.get(i)) 
        return false; 
    } 
 
    return true; 
  } 
   
  /** 
   * 检查当前左边是否在child中 
   * @param child 
   * @param x 
   * @param y 
   * @return 
   */ 
  private boolean checkpositioninchild(view child, int x, int y) 
  { 
 
    //设置了内边距,即x,y必须落入下gesturelockview的内部中间的小区域中,可以通过调整padding使得x,y落入范围不变大,或者不设置padding 
    int padding = (int) (mgesturelockviewwidth * 0.15); 
 
    if (x >= child.getleft() + padding && x <= child.getright() - padding 
        && y >= child.gettop() + padding 
        && y <= child.getbottom() - padding) 
    { 
      return true; 
    } 
    return false; 
  } 
 
  /** 
   * 通过x,y获得落入的gesturelockview 
   * @param x 
   * @param y 
   * @return 
   */ 
  private gesturelockview getchildidbypos(int x, int y) 
  { 
    for (gesturelockview gesturelockview : mgesturelockviews) 
    { 
      if (checkpositioninchild(gesturelockview, x, y)) 
      { 
        return gesturelockview; 
      } 
    } 
 
    return null; 
 
  } 
 
  /** 
   * 设置回调接口 
   * 
   * @param listener 
   */ 
  public void setongesturelockviewlistener(ongesturelockviewlistener listener) 
  { 
    this.mongesturelockviewlistener = listener; 
  } 
 
  /** 
   * 对外公布设置答案的方法 
   * 
   * @param answer 
   */ 
  public void setanswer(int[] answer) 
  { 
    this.manswer = answer; 
  } 
 
  /** 
   * 设置最大实验次数 
   * 
   * @param boundary 
   */ 
  public void setunmatchexceedboundary(int boundary) 
  { 
    this.mtrytimes = boundary; 
  } 
 
  @override 
  public void dispatchdraw(canvas canvas) 
  { 
    super.dispatchdraw(canvas); 
    //绘制gesturelockview间的连线 
    if (mpath != null) 
    { 
      canvas.drawpath(mpath, mpaint); 
    } 
    //绘制指引线 
    if (mchoose.size() > 0) 
    { 
      if (mlastpathx != 0 && mlastpathy != 0) 
        canvas.drawline(mlastpathx, mlastpathy, mtmptarget.x, 
            mtmptarget.y, mpaint); 
    } 
 
  } 
 
  public interface ongesturelockviewlistener 
  { 
    /** 
     * 单独选中元素的id 
     * 
     * @param position 
     */ 
    public void onblockselected(int cid); 
 
    /** 
     * 是否匹配 
     * 
     * @param matched 
     */ 
    public void ongestureevent(boolean matched); 
 
    /** 
     * 超过尝试次数 
     */ 
    public void onunmatchedexceedboundary(); 
  } 
} 

注释极其详细,用极其不过分~主要就是ontouchevent中对用户选择的gesturelockview进行判断,以及改变gesturelockview状态等。

5、布局文件

<relativelayout xmlns:android="http://schemas.android.com/apk/res/android" 
  xmlns:tools="http://schemas.android.com/tools" 
  xmlns:zhy="http://schemas.android.com/apk/res/com.zhy.zhy_gesturelockview" 
  android:layout_width="match_parent" 
  android:layout_height="match_parent" > 
 
  <com.zhy.zhy_gesturelockview.view.gesturelockviewgroup 
    android:id="@+id/id_gesturelockviewgroup" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:background="#f2f2f7" 
    android:gravity="center_vertical" 
    zhy:count="3" 
    zhy:trytimes="5" /> 
<!--  zhy:color_no_finger_inner_circle="#ff085d58" 
    zhy:color_no_finger_outer_circle="#ff08f0e0" 
    zhy:color_finger_on="#ff1734bf" --> 
 
</relativelayout> 

有兴趣的可以自定义属性,把注释的代码添进去就行,当然你也可以什么都不设置,单纯设置宽度和高度,我觉得默认效果也是不错的 ~

6、调用

package com.zhy.zhy_gesturelockview; 
 
import android.app.activity; 
import android.os.bundle; 
import android.widget.toast; 
 
import com.zhy.zhy_gesturelockview.view.gesturelockviewgroup; 
import com.zhy.zhy_gesturelockview.view.gesturelockviewgroup.ongesturelockviewlistener; 
 
public class mainactivity extends activity 
{ 
 
  private gesturelockviewgroup mgesturelockviewgroup; 
 
  @override 
  protected void oncreate(bundle savedinstancestate) 
  { 
    super.oncreate(savedinstancestate); 
    setcontentview(r.layout.activity_main); 
 
    mgesturelockviewgroup = (gesturelockviewgroup) findviewbyid(r.id.id_gesturelockviewgroup); 
    mgesturelockviewgroup.setanswer(new int[] { 1, 2, 3, 4,5 }); 
    mgesturelockviewgroup 
        .setongesturelockviewlistener(new ongesturelockviewlistener() 
        { 
 
          @override 
          public void onunmatchedexceedboundary() 
          { 
            toast.maketext(mainactivity.this, "错误5次...", 
                toast.length_short).show(); 
            mgesturelockviewgroup.setunmatchexceedboundary(5); 
          } 
 
          @override 
          public void ongestureevent(boolean matched) 
          { 
            toast.maketext(mainactivity.this, matched+"", 
                toast.length_short).show(); 
          } 
 
          @override 
          public void onblockselected(int cid) 
          { 
          } 
        }); 
  } 
 
}