热门标签 | 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) 
          { 
          } 
        }); 
  } 
 
} 


推荐阅读
  • Android 九宫格布局详解及实现:人人网应用示例
    本文深入探讨了人人网Android应用中独特的九宫格布局设计,解析其背后的GridView实现原理,并提供详细的代码示例。这种布局方式不仅美观大方,而且在现代Android应用中较为少见,值得开发者借鉴。 ... [详细]
  • Android LED 数字字体的应用与实现
    本文介绍了一种适用于 Android 应用的 LED 数字字体(digital font),并详细描述了其在 UI 设计中的应用场景及其实现方法。这种字体常用于视频、广告倒计时等场景,能够增强视觉效果。 ... [详细]
  • RecyclerView初步学习(一)
    RecyclerView初步学习(一)ReCyclerView提供了一种插件式的编程模式,除了提供ViewHolder缓存模式,还可以自定义动画,分割符,布局样式,相比于传统的ListVi ... [详细]
  • 深入解析Android自定义View面试题
    本文探讨了Android Launcher开发中自定义View的重要性,并通过一道经典的面试题,帮助开发者更好地理解自定义View的实现细节。文章不仅涵盖了基础知识,还提供了实际操作建议。 ... [详细]
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • 本文详细介绍了如何使用Spring Boot进行高效开发,涵盖了配置、实例化容器以及核心注解的使用方法。 ... [详细]
  • 2023年京东Android面试真题解析与经验分享
    本文由一位拥有6年Android开发经验的工程师撰写,详细解析了京东面试中常见的技术问题。涵盖引用传递、Handler机制、ListView优化、多线程控制及ANR处理等核心知识点。 ... [详细]
  • 本文介绍如何在 Unity 的 XML 配置文件中,将参数传递给自定义生命周期管理器的构造函数。我们将详细探讨 CustomLifetimeManager 类的实现及其配置方法。 ... [详细]
  • 解决微信电脑版无法刷朋友圈问题:使用安卓远程投屏方案
    在工作期间想要浏览微信和朋友圈却不太方便?虽然微信电脑版目前不支持直接刷朋友圈,但通过远程投屏技术,可以轻松实现在电脑上操作安卓设备的功能。 ... [详细]
  • 本文详细介绍了 Java 中 org.apache.xmlbeans.SchemaType 类的 getBaseEnumType() 方法,提供了多个代码示例,并解释了其在不同场景下的使用方法。 ... [详细]
  • 本文深入探讨了 com.example.android.sunshine.data.TestUtilities 中 validateThenCloseCursor() 方法的使用方法及其代码示例,旨在帮助开发者更好地理解和应用该方法。 ... [详细]
  • 基于KVM的SRIOV直通配置及性能测试
    SRIOV介绍、VF直通配置,以及包转发率性能测试小慢哥的原创文章,欢迎转载目录?1.SRIOV介绍?2.环境说明?3.开启SRIOV?4.生成VF?5.VF ... [详细]
  • 解决JAX-WS动态客户端工厂弃用问题并迁移到XFire
    在处理Java项目中的JAR包冲突时,我们遇到了JaxWsDynamicClientFactory被弃用的问题,并成功将其迁移到org.codehaus.xfire.client。本文详细介绍了这一过程及解决方案。 ... [详细]
  • 深入解析 Apache Shiro 安全框架架构
    本文详细介绍了 Apache Shiro,一个强大且灵活的开源安全框架。Shiro 专注于简化身份验证、授权、会话管理和加密等复杂的安全操作,使开发者能够更轻松地保护应用程序。其核心目标是提供易于使用和理解的API,同时确保高度的安全性和灵活性。 ... [详细]
  • 探讨如何真正掌握Java EE,包括所需技能、工具和实践经验。资深软件教学总监李刚分享了对毕业生简历中常见问题的看法,并提供了详尽的标准。 ... [详细]
author-avatar
为我有方
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有