热门标签 | HotTags
当前位置:  开发笔记 > 运维 > 正文

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

这篇文章主要介绍了一个超实用的Android手势锁制作实例教程,普通的圆环形图标变换,在App和系统的锁屏界面中都可以调用,需要的朋友可以参考下

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

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

2016426162442168.gif (441×443)

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

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

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

<&#63;xml version="1.0" encoding="utf-8"&#63;> 
 
 
   
   
   
   
   
   
 
   
     
     
     
     
     
     
   
 
 

用户可以用过在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 

注释很详细,主要就是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 mChoose = new ArrayList(); 
 
  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  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 
 
 
   
 
 
 

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

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) 
          { 
          } 
        }); 
  } 
 
} 


推荐阅读
  • 深入解析 Apache Shiro 安全框架架构
    本文详细介绍了 Apache Shiro,一个强大且灵活的开源安全框架。Shiro 专注于简化身份验证、授权、会话管理和加密等复杂的安全操作,使开发者能够更轻松地保护应用程序。其核心目标是提供易于使用和理解的API,同时确保高度的安全性和灵活性。 ... [详细]
  • 探讨如何真正掌握Java EE,包括所需技能、工具和实践经验。资深软件教学总监李刚分享了对毕业生简历中常见问题的看法,并提供了详尽的标准。 ... [详细]
  • 本文介绍如何使用布局文件在Android应用中排列多行TextView和Button,使其占据屏幕的特定比例,并提供示例代码以帮助理解和实现。 ... [详细]
  • Startup 类配置服务和应用的请求管道。Startup类ASP.NETCore应用使用 Startup 类,按照约定命名为 Startup。 Startup 类:可选择性地包括 ... [详细]
  • 创建项目:Visual Studio Online 入门指南
    本文介绍如何使用微软的 Visual Studio Online(VSO)创建和管理开发项目。作为一款基于云计算的开发平台,VSO 提供了丰富的工具和服务,简化了项目的配置和部署流程。 ... [详细]
  • FinOps 与 Serverless 的结合:破解云成本难题
    本文探讨了如何通过 FinOps 实践优化 Serverless 应用的成本管理,提出了首个 Serverless 函数总成本估计模型,并分享了多种有效的成本优化策略。 ... [详细]
  • 本文介绍了Android开发中Intent的基本概念及其在不同Activity之间的数据传递方式,详细展示了如何通过Intent实现Activity间的跳转和数据传输。 ... [详细]
  • 科研单位信息系统中的DevOps实践与优化
    本文探讨了某科研单位通过引入云原生平台实现DevOps开发和运维一体化,显著提升了项目交付效率和产品质量。详细介绍了如何在实际项目中应用DevOps理念,解决了传统开发模式下的诸多痛点。 ... [详细]
  • 优化 Android 按钮状态下的背景和文本颜色变化
    本文介绍如何通过 Android 的 Selector 实现按钮在不同状态下(如按压)的背景和文本颜色动态变化。我们将详细讲解实现步骤,并提供完整的代码示例。 ... [详细]
  • 本文详细介绍超文本标记语言(HTML)的基本概念与语法结构。HTML是构建网页的核心语言,通过标记标签描述页面内容,帮助开发者创建结构化、语义化的Web页面。 ... [详细]
  • 本文介绍了如何通过设置背景形状来轻松地为 Android 的 TextView 添加圆形边框。我们将详细讲解 XML 代码的配置,包括圆角、描边和填充等属性。 ... [详细]
  • 本文作者分享了在阿里巴巴获得实习offer的经历,包括五轮面试的详细内容和经验总结。其中四轮为技术面试,一轮为HR面试,涵盖了大量的Java技术和项目实践经验。 ... [详细]
  • 本文介绍如何使用 Android 的 Canvas 和 View 组件创建一个简单的绘图板应用程序,支持触摸绘画和保存图片功能。 ... [详细]
  • 探讨了在有序数列中实现多种查询和修改操作的高效数据结构设计,主要使用线段树与平衡树(Treap)结合的方法。 ... [详细]
  • Redis Hash 数据结构详解
    本文详细介绍了 Redis 中的 Hash 数据类型及其常用命令。Hash 类型用于存储键值对集合,支持多种操作如插入、查询、更新和删除字段值。此外,文章还探讨了 Hash 类型在实际业务场景中的应用,并提供了优化建议。 ... [详细]
author-avatar
潘多拉多宝_712
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有