android自定义View实现手势解锁

有时候为了程序的安全性,我们经常要采取一些安全措施,就像我们常用的支付宝那样,隔一定的时间再回到应用程序时会让用户利用手势去解锁应用程序,最近由于项目需求,也要求做这样一个功能,当用户切出本应用程序15分钟后回来,让用户手势解锁,整个需求的难点就在如何实现这个手势锁,开始一点头绪也没有,没有一点思路去实现这个手势解锁功能,在google了一番后看了一篇非常好的博客后,按照博主的思路的确是可以实现一个十分不错的手势锁View,也参考了下那位大神的代码,下面是我根据他的思路和代码片段实现的一个自定义手势解锁 View,先看效果图.

这是自定义View的初始效果图:

以下是绘制手势时的效果图:

下面是实现的demo代码:

package com.example.gesturelock; 

import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask; 

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View; 

import com.example.gesturelock.GestureLockView.OnGestureFinishListener; 

public class MyGestureLockView extends View { 

  /**
   * 不同状态的画笔
   */
  private Paint paintNormal;
  private Paint paintOnTouch;
  private Paint paintInnerCycle;
  private Paint paintLines;
  private Paint paintKeyError; 

  private MyCycle[] cycles;
  private Path linePath = new Path();
  private List<Integer> linedCycles = new ArrayList<Integer>();
  private OnGestureFinishListener onGestureFinishListener;
  private String key;
  private int eventX, eventY;
  private boolean canContinue = true;
  private boolean result;
  private Timer timer; 

  /**
   * 不同状态下的色值
   */
  private int OUT_CYCLE_NORMAL = Color.rgb(108, 119, 138); // ������Բ��ɫ
  private int OUT_CYCLE_ONTOUCH = Color.rgb(025, 066, 103); // ѡ����Բ��ɫ
  private int INNER_CYCLE_ONTOUCH = Color.rgb(002, 210, 255); // ѡ����Բ��ɫ
  private int LINE_COLOR = Color.argb(127, 002, 210, 255); // ��������ɫ
  private int ERROR_COLOR = Color.argb(127, 255, 000, 000); 

  public void setOnGestureFinishListener(
      OnGestureFinishListener onGestureFinishListener) {
    this.onGestureFinishListener = onGestureFinishListener;
  } 

  public void setKey(String key) {
    this.key = key;
  } 

  public MyGestureLockView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    init();
  } 

  public MyGestureLockView(Context context, AttributeSet attrs) {
    super(context, attrs);
    init();
  } 

  public MyGestureLockView(Context context) {
    super(context);
    init();
  } 

  private void init() { 

    paintNormal = new Paint();
    paintNormal.setAntiAlias(true);
    paintNormal.setStrokeWidth(3);
    paintNormal.setStyle(Paint.Style.STROKE); 

    paintOnTouch = new Paint();
    paintOnTouch.setAntiAlias(true);
    paintOnTouch.setStrokeWidth(3);
    paintOnTouch.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(6); 

    paintKeyError = new Paint();
    paintKeyError.setAntiAlias(true);
    paintKeyError.setStyle(Paint.Style.STROKE);
    paintKeyError.setStrokeWidth(3); 

  } 

  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    // TODO Auto-generated method stub
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
  } 

  @Override
  protected void onLayout(boolean changed, int left, int top, int right,
      int bottom) {
    // TODO Auto-generated method stub
    super.onLayout(changed, left, top, right, bottom);
    int perSize = 0;
    if (cycles == null && (perSize = getWidth() / 6) > 0) { 

      cycles = new MyCycle[9];
      for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
          MyCycle cycle = new MyCycle();
          cycle.setNum(i * 3 + j);
          cycle.setOx(perSize * (j * 2 + 1));
          cycle.setOy(perSize * (i * 2 + 1));
          cycle.setR(perSize * 0.5f);
          cycles[i * 3 + j] = cycle;
        }
      }
    }
  } 

  /**
   * 绘制所需要绘制的内容
   */
  @Override
  protected void onDraw(Canvas canvas) {
    // TODO Auto-generated method stub
    super.onDraw(canvas);
    for (int i = 0; i < cycles.length; i++) { 

      if (!canContinue && !result) {
        paintOnTouch.setColor(ERROR_COLOR);
        paintInnerCycle.setColor(ERROR_COLOR);
        paintLines.setColor(ERROR_COLOR);
      } else if (cycles[i].isOnTouch()) {
        paintOnTouch.setColor(OUT_CYCLE_ONTOUCH);
        paintInnerCycle.setColor(INNER_CYCLE_ONTOUCH);
        paintLines.setColor(LINE_COLOR);
      } else {
        paintNormal.setColor(OUT_CYCLE_NORMAL);
        paintInnerCycle.setColor(INNER_CYCLE_ONTOUCH);
        paintLines.setColor(LINE_COLOR);
      } 

      if (cycles[i].isOnTouch()) {
        canvas.drawCircle(cycles[i].getOx(), cycles[i].getOy(),
            cycles[i].getR(), paintOnTouch);
        drawInnerBuleCycle(cycles[i], canvas);
      } else { 

        canvas.drawCircle(cycles[i].getOx(), cycles[i].getOy(),
            cycles[i].getR(), paintNormal);
      }
    }
    drawLine(canvas);
  } 

  /**
   * 绘制大圆里的小圆
   *
   * @param canvas
   */
  private void drawInnerBuleCycle(MyCycle cycle, Canvas canvas) {
    canvas.drawCircle(cycle.getOx(), cycle.getOy(), cycle.getR() / 3,
        paintInnerCycle);
  } 

  private void drawLine(Canvas canvas) {
    linePath.reset();
    if (linedCycles.size() > 0) {
      for (int i = 0; i < linedCycles.size(); i++) {
        int index = linedCycles.get(i);
        if (i == 0) {
          // 设置为整条路径的起点
          linePath.moveTo(cycles[index].getOx(), cycles[i].getOy());
        } else {
          linePath.lineTo(cycles[i].getOx(), cycles[i].getOy());
        }
      }
      linePath.lineTo(eventX, eventY);
      canvas.drawPath(linePath, paintLines);
    }
  } 

  /**
   * 根据手择时触摸点的不同,修改对应的状态值
   */
  @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 < cycles.length; 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 sb = new StringBuffer();
        for (int i = 0; i < linedCycles.size(); i++) {
          sb.append(linedCycles.get(i));
        }
        result = key.equals(sb.toString());
        if (onGestureFinishListener != null) {
          onGestureFinishListener.OnGestureFinish(result);
        }
        timer = new Timer();
        timer.schedule(new TimerTask() { 

          @Override
          public void run() {
            // 回到初始状态
            eventX = eventY = 0;
            for (int i = 0; i < cycles.length; i++) {
              cycles[i].setOnTouch(false);
            }
            linedCycles.clear();
            linePath.reset();
            canContinue = true;
            postInvalidate();
          }
        }, 1000);
        break;
      }
    }
    invalidate();
    return true;
  }
} 

自定义圆类:

package com.example.gesturelock; 

public class MyCycle {
  private int ox;     // Բ�ĺ�����
  private int oy;     // Բ��������
  private float r;     // �뾶����
  private Integer num;   // ������ֵ
  private boolean onTouch; // false=δѡ��
  public int getOx() {
    return ox;
  }
  public void setOx(int ox) {
    this.ox = ox;
  }
  public int getOy() {
    return oy;
  }
  public void setOy(int oy) {
    this.oy = oy;
  }
  public float getR() {
    return r;
  }
  public void setR(float r) {
    this.r = r;
  }
  public Integer getNum() {
    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 < r;
  }
} 

思路:

1.自定义一个 View和MyCircle类,将九个MyCircle类的实例绘制到View中.

2.处理onTouch事件,根据不同的事件修改MyCircle实例的状态,并调用更新invaildate更新View

3.重写onDraw()方法,根据不同的状态去重新绘制整个View

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

(0)

相关推荐

  • Android 自定义九宫格手势锁

    预览效果图如下: 主要的方法是重写View.onTouchEvent( MotionEvent event ) , 常用的三个操作:ACTION_DOWN 手指触摸屏幕 ; ACTION_UP 手指离开屏幕; ACTION_MOVE手指在屏幕滑动. 如果该方法返回true ,表示该事件已经被View处理,不再向上层的View或Activity传递 : 如果返回false, 表示事件未处理,继续传递. 具体代码如下: package com.ninegrid; import android.con

  • Android九宫格手势密码代码设计

    最近因为项目需要用到九宫格密码(也叫手势轨迹密码),特地去学习了一下九宫格密码的实现原来.可能有人认为九宫格密码事例网上到处都有,很多甚至直接拷贝过来就可以运行为什么还要学习呢.还特地写到网上有必要吗?其实写这个目的是为了增强和锻炼自己的语言组织能力.其实如果只是既然是学习就不光是要知道答案(完成效果)更重要的是知道他什么实现. 好了题外话就不多说了,要实现九宫格密码要解决的问题有: 1.给九宫格密码界面布局九个点,即确定每个节点的位置.每个点到上下左右的距离都是相同的.即九个点刚好围成一个正方

  • Android实现九宫格手势解锁

    本文为大家分享了Android九宫格手势解锁的具体代码,供大家参考,具体内容如下 这里是使用的开源库GestureLibray 里面有关于这个东西的介绍和接入方式,这里就不累赘了,我只是说下里面没有的. 关于这个库的使用: protected void initViews() { //设置模式 LockMode lockMode = (LockMode) getIntent().getSerializableExtra(Config.INTENT_SECONDACTIVITY_KEY); //是

  • Android 5秒学会使用手势解锁功能

    Android手势解锁 本文讲述的是一个手势解锁的库,可以定制显示隐藏宫格点.路径.并且带有小九宫格显示图,和震动!让你学会使用这个简单,高效的库! 先来一波效果效果展示: 手势解锁效果 今天给大家介绍的是本人良心制作的一个手势解锁开源库,大家有什么建议和想法都可以发到我的邮箱: diosamolee2014@gmail.com 或者评论,我会为大家提供我力所能及的帮助! GitHub地址: https://github.com/Diosamo/Gesture_Lock 添加依赖: 添加的gra

  • Android仿支付宝手势密码解锁功能

    Starting 创建手势密码可以查看 CreateGestureActivity.java 文件. 登陆验证手势密码可以看 GestureLoginActivity.java 文件. Features 使用了 JakeWharton/butterknife butterknife 使用了 ACache 来存储手势密码 /** * 保存手势密码 */ private void saveChosenPattern(List<LockPatternView.Cell> cells) { byte[

  • android自定义View实现手势解锁

    有时候为了程序的安全性,我们经常要采取一些安全措施,就像我们常用的支付宝那样,隔一定的时间再回到应用程序时会让用户利用手势去解锁应用程序,最近由于项目需求,也要求做这样一个功能,当用户切出本应用程序15分钟后回来,让用户手势解锁,整个需求的难点就在如何实现这个手势锁,开始一点头绪也没有,没有一点思路去实现这个手势解锁功能,在google了一番后看了一篇非常好的博客后,按照博主的思路的确是可以实现一个十分不错的手势锁View,也参考了下那位大神的代码,下面是我根据他的思路和代码片段实现的一个自定义

  • Android自定义view实现滑动解锁效果

    本文实例为大家分享了Android自定义view实现滑动解锁的具体代码,供大家参考,具体内容如下 1. 需求如下: 近期需要做一个类似屏幕滑动解锁的功能,右划开始,左划暂停. 2. 需求效果图如下 3. 实现效果展示 4. 自定义view如下 /** * Desc 自定义滑动解锁View * Author ZY * Mail sunnyfor98@gmail.com * Date 2021/5/17 11:52 */ @SuppressLint("ClickableViewAccessibili

  • Android自定义View九宫格手势密码解锁

    由于公司新的项目需要用到九宫格手势密码解锁的功能,于是觉得自己写一个.废话不多说,直接上效果图: 首选我们来分析下实现的思路: 1. 绘制出相对于这个View的居中的九个点,作为默认状态的点 2. 点击屏幕的时候是否点击在这九个点上 3. 在屏幕上滑动的时候,绘制两个点之间的线条,以及选中状态的点 4. 手指离开屏幕的时候判断手势密码是否正确,如若错误这把错误状态下的点和线绘制出来. 具体实现: 首先我们得绘制出默认正常状态下的九个点: /** * 点的bean * Created by Adm

  • Android自定义View手势密码

    Android 自定义View 当然是十分重要的,笔者这两天写了一个自定义 View 的手势密码,和大家分享分享: 首先,我们来创建一个表示点的类,Point.java: public class Point { // 点的三种状态 public static final int POINT_STATUS_NORMAL = 0; public static final int POINT_STATUS_CLICK = 1; public static final int POINT_STATUS

  • Android自定义View实现九宫格图形解锁(Kotlin版)

    本文实例为大家分享了Android自定义View实现九宫格图形解锁的具体代码,供大家参考,具体内容如下 效果: 代码: package com.example.kotlin_test import android.content.Context import android.graphics.Canvas import android.graphics.Color import android.graphics.Paint import android.util.AttributeSet imp

  • Android自定义View实现开关按钮

    前言:Android自定义View对于刚入门乃至工作几年的程序员来说都是非常恐惧的,但也是Android进阶学习的必经之路,平时项目中经常会有一些苛刻的需求,我们可以在GitHub上找到各种各样的效果,能用则用,不能用自己花功夫改改也能草草了事.不过随着工作经验和工作性质,越来越觉得自定义View是时候有必要自己花点功夫研究一下. 一.经过这两天的努力,自己也尝试着写了一个Demo,效果很简单,就是开关按钮的实现. 可能有的人会说这效果so easy,找UI切三张图就完事了,何必大费周折自定义.

  • Android 自定义TextView实现滑动解锁高亮文字

    下面一段代码给大家分享Android 自定义TextView实现滑动解锁高亮文字效果,具体代码如下所示: public class HightLightTextView extends TextView { // 存储view的宽度 private int mTextViewWidth = 0; // 画笔 private Paint mPaint; // 线性渲染 private LinearGradient mLinearGradient; // 存储变换的matrix private Ma

  • Android自定义View实现分段选择按钮的实现代码

    首先演示下效果,分段选择按钮,支持点击和滑动切换. 视图绘制过程中,要执行onMeasure.onLayout.onDraw等方法,这也是自定义控件最常用到的几个方法. onMeasure:测量视图的大小,可以根据MeasureSpec的Mode确定父视图和子视图的大小. onLayout:确定视图的位置 onDraw:绘制视图 这里就不做过多的介绍,主要介绍本控件涉及的到的部分. 1.1 获取item大小.起始位置 @Override protected void onMeasure(int

  • Android自定义view之3D正方体效果实例

    目录 前言 一.小提 二.将传感器改成事件分发机制 三.使用 四.源码 总结 前言 在之前写了一篇关于3D效果的文章,借助传感器展示,有小伙伴问可不可以改成手势滑动操作(事件分发),所以出一篇文章 传感器相关文章链接:Android 3D效果的实现 一.小提 相对于常见的自定义view而言,继承的GLSurfaceView只有两个构造函数.可以理解为没有提供获取自定义属性的方法. public TouchSurfaceView(Context context) { super(context);

  • Android自定义view实现阻尼效果的加载动画

    效果: 需要知识: 1. 二次贝塞尔曲线 2. 动画知识 3. 基础自定义view知识 先来解释下什么叫阻尼运动 阻尼振动是指,由于振动系统受到摩擦和介质阻力或其他能耗而使振幅随时间逐渐衰减的振动,又称减幅振动.衰减振动.[1] 不论是弹簧振子还是单摆由于外界的摩擦和介质阻力总是存在,在振动过程中要不断克服外界阻力做功,消耗能量,振幅就会逐渐减小,经过一段时间,振动就会完全停下来.这种振幅随时间减小的振动称为阻尼振动.因为振幅与振动的能量有关,阻尼振动也就是能量不断减少的振动.阻尼振动是非简谐运

随机推荐