项目中用到手势解锁,然而没有在GitHub上找到想要的样式= =,仅仅好自己来定义了。以下来看代码~~

基本上非常多应用的手势解锁全都是九宫格的,内部内就是九个小圈圈而已。

那么我们就先来自己定义这个小圈圈吧~

圈圈的颜色选择状态有大致有三种状态。所以我定义了一个枚举来区分

package com.juzisang.com.library;/*** Created by 橘子桑 on 2016/3/27.*/
public enum LockState {SELECT_STATE,//选中ERRER_STATE, //错误DEFAULT_COLOR //默认
}

圈圈分为边框。内部填充色。还有内部圆。所以我定义了三个画笔来区分。

package com.juzisang.com.library;import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;/*** Created by 橘子桑 on 2016/3/27.*/
public class MarkerView extends View {//是否显示内部的圈圈private boolean mInsideNodeShow;//宽度protected int mContentWidth;//宽度protected int mContentRadius;//选中状态protected LockState mCurrentState = LockState.DEFAULT_COLOR;//画边框画圆的的画笔private Paint mNodeFramePaint;private Paint mNodeCirclePaint;private Paint mNodeFullPaint;//默认的颜色private int mDefaultColor = Color.parseColor("#757575");private int mDefailtFullColor = Color.parseColor("#64757575");private int mNodeDefaultColor = Color.parseColor("#757575");//选中的颜色private int mSelectColor = Color.parseColor("#7ECEF4");private int mFrameSelectFullColor = Color.parseColor("#647ECEF4");private int mNodeSelectColor = Color.parseColor("#7ECEF4");//错误时候的颜色private int mErrerColor = Color.parseColor("#EC6941");private int mErrerFullColor = Color.parseColor("#64EC6941");private int mErrerNodeColor = Color.parseColor("#EC6941");//边框的宽度private int mFrameLineWidth;private int mNodeRadius;//每一个圈圈的内边距private int mNodePadding;//触摸有效的范围private float mTouchRatio;//当前标记的位置private int mNum;public MarkerView(Context context, AttributeSet attrs) {super(context, attrs);initView(context, attrs, 0);}public MarkerView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);initView(context, attrs, defStyleAttr);}//以后外部布局传来的參数public MarkerView(Context context, int mDefaultColor, int mDefailtFullColor, int mNodeDefaultColor,int mSelectColor, int mFrameSelectFullColor, int mNodeSelectColor,int mErrerColor, int mErrerFullColor, int mErrerNodeColor,int mFrameLineWidth, int mNodeRadius, int mNodePadding, boolean insideNodeShow) {super(context);this.mInsideNodeShow = insideNodeShow;this.mDefaultColor = mDefaultColor;this.mDefailtFullColor = mDefailtFullColor;this.mNodeDefaultColor = mNodeDefaultColor;this.mSelectColor = mSelectColor;this.mFrameSelectFullColor = mFrameSelectFullColor;this.mNodeSelectColor = mNodeSelectColor;this.mErrerColor = mErrerColor;this.mErrerFullColor = mErrerFullColor;this.mErrerNodeColor = mErrerNodeColor;this.mFrameLineWidth = mFrameLineWidth;this.mNodeRadius = mNodeRadius;this.mNodePadding = mNodePadding;//内边距setPadding(mNodePadding, mNodePadding, mNodePadding, mNodePadding);//外部圆mNodeFramePaint = new Paint();mNodeFramePaint.setColor(mDefaultColor);mNodeFramePaint.setAntiAlias(true);mNodeFramePaint.setStrokeWidth(mFrameLineWidth);mNodeFramePaint.setStyle(Paint.Style.STROKE);//仅仅画出边框//内部填充色mNodeFullPaint = new Paint();mNodeFullPaint.setColor(mDefailtFullColor);mNodeFullPaint.setStyle(Paint.Style.FILL);mNodeFullPaint.setAntiAlias(true);//内部圆mNodeCirclePaint = new Paint();mNodeCirclePaint.setColor(mNodeDefaultColor);mNodeCirclePaint.setStyle(Paint.Style.FILL);//填充mNodeCirclePaint.setAntiAlias(true);}//取当前透明度的百分比public int getFullAlpha(int color, float ratio) {return Color.argb((int) (Color.alpha(color) * ratio), Color.red(color), Color.green(color), Color.blue(color));}@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);mContentWidth = getWidth();mContentRadius = mContentWidth / 2 - Math.abs(getPaddingLeft()) - mFrameLineWidth / 2;}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);switch (mCurrentState) {case DEFAULT_COLOR: //默认mNodeFramePaint.setColor(mDefaultColor);mNodeFullPaint.setColor(mDefailtFullColor);mNodeCirclePaint.setColor(mNodeDefaultColor);//外圆canvas.drawCircle(mContentWidth / 2, mContentWidth / 2, mContentRadius, mNodeFramePaint);//填充色canvas.drawCircle(mContentWidth / 2, mContentWidth / 2, mContentRadius - mFrameLineWidth / 2, mNodeFullPaint);//中心圆if (mInsideNodeShow)canvas.drawCircle(mContentWidth / 2, mContentWidth / 2, mNodeRadius, mNodeCirclePaint);break;case ERRER_STATE://错误mNodeFramePaint.setColor(mErrerColor);mNodeFullPaint.setColor(mErrerFullColor);mNodeCirclePaint.setColor(mErrerNodeColor);//外圆canvas.drawCircle(mContentWidth / 2, mContentWidth / 2, mContentRadius, mNodeFramePaint);//填充色canvas.drawCircle(mContentWidth / 2, mContentWidth / 2, mContentRadius - mFrameLineWidth / 2, mNodeFullPaint);//中心圆canvas.drawCircle(mContentWidth / 2, mContentWidth / 2, mNodeRadius, mNodeCirclePaint);break;case SELECT_STATE://选中mNodeFramePaint.setColor(mSelectColor);mNodeFullPaint.setColor(mFrameSelectFullColor);mNodeCirclePaint.setColor(mNodeSelectColor);//外圆canvas.drawCircle(mContentWidth / 2, mContentWidth / 2, mContentRadius, mNodeFramePaint);//填充色canvas.drawCircle(mContentWidth / 2, mContentWidth / 2, mContentRadius - mFrameLineWidth / 2, mNodeFullPaint);//中心圆canvas.drawCircle(mContentWidth / 2, mContentWidth / 2, mNodeRadius, mNodeCirclePaint);break;}}//设置状态,而且重绘public void setState(LockState CurrentState) {mCurrentState = CurrentState;invalidate();}//是否选中public boolean isHighLighted() {if (mCurrentState == LockState.SELECT_STATE || mCurrentState == LockState.ERRER_STATE) {return true;}return false;}//中心点Xpublic int getCenterX() {return (getLeft() + getRight()) / 2;}//中心点Ypublic int getCenterY() {return (getTop() + getBottom()) / 2;}//设置圈圈在手势锁其中的位置protected void setNum(int num) {mNum = num;}protected int getNum() {return mNum;}
}

以上就是一个简单的圆了

那么,自己定义View当然会有自己定义属性,所以有这么多T0T,不要问我为什么这么多属性。任性= =(事实上我还想写很多其它),自己定义属性的方法

 <!-- 线的颜色 --><attr name="lineColor" format="color" /><!-- 线的宽度 --><attr name="lineWidth" format="dimension" /><!--默认颜色 --><attr name="defaultColor" format="color" /><!--默认时的填充色--><attr name="defaultFullColor" format="color" /><!--默认内部圆颜色--><attr name="defaultNodeColor" format="color" /><!-- ======================================================= --><!-- 边框选中时边框的颜色 --><attr name="selectColor" format="color" /><!-- 边框选中时内部的填充色 --><attr name="selectFrameFullColor" format="color" /><!--内部圆圈选中时的颜色--><attr name="selectNodeColor" format="color" /><!-- ======================================================= --><!-- 错误的颜色 --><attr name="errorColor" format="color" /><!--错误时内部的填充色--><attr name="errorFullColor" format="color" /><!-- 错误时的颜色 --><attr name="errorNodeColor" format="color" /><!-- ======================================================= --><!--边框的的宽度--><attr name="frameLineWidth" format="dimension" /><!-- 内部圆圈的宽度 --><attr name="nodeRadius" format="dimension" /><!--内边距--><attr name="nodePadding" format="dimension" /><!--触摸有效的比例--><attr name="touchRatio" format="float" /><!-- 是否显示内部的圆圈 --><attr name="insideNodeShow" format="boolean"/>

LockView的代码

package com.juzisang.com.library;import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.ViewGroup;import java.util.ArrayList;/*** Created by 橘子桑 on 2016/3/27.*/
public class LockView extends ViewGroup {//画连接线的画笔private Paint mLinePaint;//能够触摸的区域百分比private float mTouchRatio;//线的颜色protected int mLineColor;//先的宽度protected float mLineWidth;//已经选中了的ViewArrayList<MarkerView> mNodeViews = new ArrayList<>();//存储passwordprotected StringBuilder pawBuilder = new StringBuilder();//当前手指触摸的x坐标protected float x;//当前手指触摸的y坐标protected float y;//回调private onLockCallback mOnLockCallback;protected int mDefaultColor;protected int mSelectColor;protected int mErrerColor;//禁用手势锁private boolean mLockScreen;private boolean isTouch;//是否把连接线绘制在子View的上面private boolean mLineTop = false;//手指离开马上重绘private boolean mFingerLeaveRedraw = true;public LockView(Context context) {this(context, null);}public LockView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public LockView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);initView(context, attrs, defStyleAttr);}protected void initView(Context context, AttributeSet attrs, int defStyleAttr) {TypedArray r = context.obtainStyledAttributes(attrs, R.styleable.MarkerView);boolean insideNodeShow = r.getBoolean(R.styleable.LockView_insideNodeShow, false);//默认的颜色mDefaultColor = r.getColor(R.styleable.LockView_defaultColor, context.getResources().getColor(android.R.color.holo_blue_dark));int mDefailtFullColor = r.getColor(R.styleable.LockView_defaultFullColor, getFullAlpha(mDefaultColor, 0.3F));int mNodeDefaultColor = (int) r.getColor(R.styleable.LockView_defaultNodeColor, mDefaultColor);//选中的颜色mSelectColor = (int) r.getColor(R.styleable.LockView_selectColor, context.getResources().getColor(android.R.color.holo_blue_light));int mFrameSelectFullColor = r.getColor(R.styleable.LockView_selectFrameFullColor, getFullAlpha(mSelectColor, 0.3F));int mNodeSelectColor = r.getColor(R.styleable.LockView_selectNodeColor, mSelectColor);//错误时候的颜色mErrerColor = r.getColor(R.styleable.LockView_errorColor, context.getResources().getColor(android.R.color.holo_red_light));int mErrerFullColor = r.getColor(R.styleable.LockView_errorFullColor, getFullAlpha(mErrerColor, 0.3F));int mErrerNodeColor = r.getColor(R.styleable.LockView_errorNodeColor, mErrerColor);//圆框变的宽度int mFrameLineWidth = (int) r.getDimension(R.styleable.LockView_frameLineWidth, DensityUtils.dip2px(context, 5));//内圆的直径int mNodeRadius = (int) r.getDimension(R.styleable.LockView_nodeRadius, DensityUtils.dip2px(context, 5));//内边距int mNodePadding = (int) r.getDimension(R.styleable.LockView_nodePadding, DensityUtils.dip2px(context, 10));//触摸有效区域mTouchRatio = r.getFloat(R.styleable.LockView_touchRatio, mTouchRatio);mLineColor = r.getColor(R.styleable.LockView_lineColor, mDefaultColor);mLineWidth = r.getDimension(R.styleable.LockView_lineWidth, DensityUtils.dip2px(context, 5));r.recycle();//设置线的颜色mLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);mLinePaint.setColor(mLineColor);mLinePaint.setStyle(Paint.Style.STROKE);mLinePaint.setStrokeWidth(mLineWidth);mLinePaint.setStrokeCap(Paint.Cap.ROUND);mLinePaint.setStrokeJoin(Paint.Join.ROUND);for (int i = 0; i < 9; i++) {MarkerView view = new MarkerView(context, mDefaultColor, mDefailtFullColor, mNodeDefaultColor, mSelectColor, mFrameSelectFullColor, mNodeSelectColor,mErrerColor, mErrerFullColor, mErrerNodeColor, mFrameLineWidth, mNodeRadius, mNodePadding, insideNodeShow);view.setNum(i + 1);ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);view.setLayoutParams(params);addView(view);}// 清除FLAG,否则 onDraw() 不会调用。原因是 ViewGroup 默认透明背景不须要调用 onDraw()setWillNotDraw(false);}public int getFullAlpha(int color, float ratio) {return Color.argb((int) (Color.alpha(color) * ratio), Color.red(color), Color.green(color), Color.blue(color));}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {int size = Math.min(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.getSize(heightMeasureSpec)); // 測量宽度setMeasuredDimension(size, size);for (int i = 0; i < getChildCount(); i++) {measureChild(getChildAt(i), widthMeasureSpec, heightMeasureSpec);}}@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {if (changed) {float areaWidth = (r - l - getPaddingLeft() * 2) / 3;for (int n = 0; n < 9; n++) {MarkerView node = (MarkerView) getChildAt(n);// 获取3*3宫格内坐标int row = n / 3;int col = n % 3;//加上内间距int left = (int) (getPaddingLeft() + col * areaWidth);int top = (int) (getPaddingTop() + row * areaWidth);int right = (int) (left + areaWidth);int bottom = (int) (top + areaWidth);node.layout(left, top, right, bottom);}}}/*** 设置连接线是否绘制在子View的上面* true 绘制在子View的上面* false 绘制在子View的以下** @param isLineTop 设置连接线是否绘制在子View的上面*/public void setLineTop(boolean isLineTop) {mLineTop = isLineTop;invalidate();}/*** 设置连接线是否绘制在子View的上面* true 绘制在子View的上面* false 绘制在子View的以下*/public boolean getLineTop() {return mLineTop;}@Overridepublic boolean onTouchEvent(MotionEvent event) {if (getLockScreen()) {invalidate();return false;}switch (event.getAction()) {case MotionEvent.ACTION_DOWN://恢复默认resetDefault();x = event.getX();y = event.getY();isTouch = true;break;case MotionEvent.ACTION_MOVE:x = event.getX(); // 这里要实时记录手指的坐标y = event.getY();MarkerView nodeView = getNodeAt(x, y);//没有选中if (nodeView != null && !nodeView.isHighLighted()) {nodeView.setState(LockState.SELECT_STATE);mNodeViews.add(nodeView);//进度if (mOnLockCallback != null) {pawBuilder.setLength(0);for (MarkerView markerView : mNodeViews) {pawBuilder.append(markerView.getNum());}mOnLockCallback.onProgress(pawBuilder.toString(), nodeView.getNum());}}if (mNodeViews.size() > 0) {invalidate();}break;case MotionEvent.ACTION_UP:LogUtils.i("手指抬起了");isTouch = false;pawBuilder.setLength(0);if (mNodeViews.size() <= 0) return true;pawBuilder.delete(0, pawBuilder.length());if (mOnLockCallback != null) {for (MarkerView markerView : mNodeViews) {pawBuilder.append(markerView.getNum());}mOnLockCallback.onFinish(pawBuilder.toString());}if (mFingerLeaveRedraw) {resetDefault();} else {invalidate();}break;}return true;}@Overrideprotected void onDraw(Canvas canvas) {//线画在子view的以下if (!mLineTop) onDrawLock(canvas);}//画子View的地方protected void dispatchDraw(Canvas canvas) {super.dispatchDraw(canvas);//放在这里的原因是。线会被子View挡到if (mLineTop) onDrawLock(canvas);}/*** 绘图的方法*/private void onDrawLock(Canvas canvas) {//屏幕锁住了,仅仅画起点到终点的if (getLockScreen()) {onDrawNodeViewLock(canvas);return;}if (isTouch || mFingerLeaveRedraw) {//从第一个和最后一个的连接线onDrawNodeViewLock(canvas);//最后一个点,到手指之间的线if (mNodeViews.size() > 0) {MarkerView lastNode = mNodeViews.get(mNodeViews.size() - 1);canvas.drawLine(lastNode.getCenterX(), lastNode.getCenterY(), x, y, mLinePaint);}} else {//假设手指离开屏幕。而且设置了手指离开马上重绘onDrawNodeViewLock(canvas);}}private void onDrawNodeViewLock(Canvas canvas) {//从第一个和最后一个的连接线for (int i = 1; i < mNodeViews.size(); i++) {MarkerView frontNode = mNodeViews.get(i - 1);MarkerView backNode = mNodeViews.get(i);canvas.drawLine(frontNode.getCenterX(), frontNode.getCenterY(), backNode.getCenterX(), backNode.getCenterY(), mLinePaint);}}/*** 获取给定坐标点的Node,返回null表示当前手指在两个Node之间*/private MarkerView getNodeAt(float x, float y) {for (int n = 0; n < getChildCount(); n++) {MarkerView node = (MarkerView) getChildAt(n);//计算触摸区域以外的距离float ratioPadding = (node.getWidth() - (node.getWidth() * mTouchRatio)) / 2;if (!(x >= node.getLeft() + ratioPadding && x < node.getRight() - ratioPadding)) {continue;}if (!(y >= node.getTop() + ratioPadding && y < node.getBottom() - ratioPadding)) {continue;}return node;}return null;}/*** 设置连接线的颜色** @param color 颜色值*/public void setLineColor(int color) {mLinePaint.setColor(color);}/*** 手指离开马上重绘*/public void setfingerLeaveRedraw(boolean mFingerLeaveRedraw) {this.mFingerLeaveRedraw = mFingerLeaveRedraw;}public boolean getfingerLeaveRedraw() {return this.mFingerLeaveRedraw;}/*** 重置状态 为默认状态*/public void resetDefault() {setState(LockState.DEFAULT_COLOR);mNodeViews.clear();}/*** 重置状态错误状态*/public void resetErrer() {setState(LockState.ERRER_STATE);}/*** 重置为选中状态*/public void resetSelect() {setState(LockState.SELECT_STATE);}/*** 锁屏,不同意触摸*/public void LockScreen(boolean isScreen) {mLockScreen = isScreen;}public boolean getLockScreen() {return mLockScreen;}public void setState(LockState state) {switch (state) {case DEFAULT_COLOR:case SELECT_STATE:setLineColor(mSelectColor);break;case ERRER_STATE:setLineColor(mErrerColor);break;}int size = mNodeViews.size();for (int i = 0; i < size; i++) {mNodeViews.get(i).setState(state);}invalidate();}public void setLockCallback(onLockCallback lockCallback) {mOnLockCallback = lockCallback;}//回调public interface onLockCallback {void onProgress(String paw, int current);void onFinish(String paw);}
}

以上凝视都写的非常清晰了。以下讲一下遇到的一些问题。

1.画出来的线被上面的圈圈覆盖了。

通过百度。知道ViewGroup的onDraw是画布局中的内容的,画子View的的方法在这种方法的后面运行。所以ViewGroup的内容会被子View覆盖。那么怎么才干把连接线画在子View的上面呢,非常easy
仅仅要在画子View的方法中运行就好了

//画子View的地方protected void dispatchDraw(Canvas canvas) {super.dispatchDraw(canvas);//放在这里的原因是。线会被子View挡到if (mLineTop) onDrawLock(canvas);}

以下是View的draw()方法

 @CallSuperpublic void draw(Canvas canvas) {final int privateFlags = mPrivateFlags;final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&(mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;// Step 1, draw the background, if neededint saveCount;if (!dirtyOpaque) {drawBackground(canvas);}// skip step 2 & 5 if possible (common case)final int viewFlags = mViewFlags;boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;if (!verticalEdges && !horizontalEdges) {// Step 3, draw the contentif (!dirtyOpaque) onDraw(canvas);// Step 4, draw the children//这里就是画子View的方法了dispatchDraw(canvas);// Overlay is part of the content and draws beneath Foregroundif (mOverlay != null && !mOverlay.isEmpty()) {mOverlay.getOverlayView().dispatchDraw(canvas);}// Step 6, draw decorations (foreground, scrollbars)onDrawForeground(canvas);// we're done...return;}

2.怎么设置触摸的区域?

    /*** 获取给定坐标点的Node,返回null表示当前手指在两个Node之间*/private MarkerView getNodeAt(float x, float y) {for (int n = 0; n < getChildCount(); n++) {MarkerView node = (MarkerView) getChildAt(n);//计算触摸区域以外的距离float ratioPadding = (node.getWidth() - (node.getWidth() * mTouchRatio)) / 2;if (!(x >= node.getLeft() + ratioPadding && x < node.getRight() - ratioPadding)) {continue;}if (!(y >= node.getTop() + ratioPadding && y < node.getBottom() - ratioPadding)) {continue;}return node;}return null;}

看上面代码。
依据圆圈的宽度减去可触摸区域的长度除2。得到可触摸区域距离边框的距的距离。

光看代码看着有点圆。画个图看一下吧

画个图是不是清晰非常多,仅仅要用getLeft+边距。和getRight-边距,就能得到可触摸区域在x轴上的范围了。Y轴同理。不懂的同学自己用笔画一下吧~

几乎相同就上面两个问题了

下载地址

转载于:https://www.cnblogs.com/yangykaifa/p/7338215.html

自己定义九宫格手势解锁相关推荐

  1. Android自定义九宫格手势解锁组件

    项目来源 别的不说,先看一下效果图: 九宫格手势图案解锁功能在很多应用中都在使用,本文介绍的组件来自于开源项目PatternLocker的翻写,原工程是使用Kotlin开发的,由于我们项目是使用jav ...

  2. Android进阶之自定义View实战(二)九宫格手势解锁实现

    一.引言 在上篇博客Android进阶之自定义View实战(一)仿iOS UISwitch控件实现中我们主要介绍了自定义View的最基本的实现方法.作为自定义View的入门篇,仅仅介绍了Canvas的 ...

  3. Qt+VS 自定义对话框 九宫格手势解锁

    一个项目,同事让界面上做个密码权限控制,防止客户误操作,由于设备一般不接键盘,输密码就太麻烦了,干脆模仿手机的手势解锁做了个对话框.网上找了些资源,代码都不太全,只能按照自己的理解做了一个,退回功能实 ...

  4. iOS-高仿支付宝手势解锁(九宫格)

    概述 高仿支付宝手势解锁, 通过手势枚举去实现手势密码相对应操作. 详细 代码下载:http://www.demodashi.com/demo/10706.html 基上篇[TouchID 指纹解锁] ...

  5. 自定义View----Android九宫格手势密码解锁

    好久没更新blog了,最近公司比较忙,旧的项目上线时间赶.加上新的项目又来了,于是导致都好久没去鸿洋的群里扯蛋了,做了一个不称职的管理员.说了好多遍的自定义萌系进度条都没有分享出来,在这给群里的各位说 ...

  6. 9宫格解锁 android_9个点的所有解锁图_Android九宫格手势锁设定和解锁

    最近在做APP的自动化测试,采用的是Appium方案.在测试过程中遇到了九宫格滑动解锁的问题,通过查阅相关资料,我做了一个通用的方法来处理九宫格在一个view中显示的情况. 这种情况我们只能通过定位每 ...

  7. (4.2.43)手势解锁之九宫格控件GestureLockView

    /*** 手势解锁*/ public class GestureLockView extends View implements GestureLockViewController {/*** 控件整 ...

  8. HTML5 Canvas简简单单实现手机九宫格手势密码解锁

    From http://www.cnblogs.com/amylis_chen/p/4142588.html#3117954 早上花了一个半小时写了一个基于HTML Canvas的手势解锁,主要是为了 ...

  9. html5手机密码修改,HTML5 Canvas简简单单实现手机九宫格手势密码解锁

    早上花了一个半小时写了一个基于HTML Canvas的手势解锁,主要是为了好玩,可能以后会用到. 思路:根据配置计算出九个点的位置,存入一个数组,当然存入数组的顺序的索引是: 第一行:0   1  2 ...

最新文章

  1. 服务器显示内存已超标,服务器显示内存已超标
  2. pyqt designer connect无响应_【JavaWeb】HTTP协议的请求与响应
  3. sql怎么实现取当前数据以及累计7天数据_年薪60万+大佬吐血整理字节跳动大数据面试真题...
  4. Esper系列(十二)Variables and Constants
  5. 神策数据正式成为国家级信创工委会成员单位!
  6. cocoapods的安装(这真是一个神奇的东西,每次安装的方法都不一样,而且很容易出现各种各样的错误)...
  7. 风压和功率计算公式轴流式_水泵和风机的功率计算及风量、风压的附加系数
  8. 仓库货位卡标识牌_仓库货架能解决传统仓储的哪些问题?
  9. KuaiRec | 快手发布首个稠密度高达99%的推荐数据集, 可用于多种推荐系统方向研究...
  10. Webpack+Babel+React环境搭建
  11. 城管系统服务器,数字城管系统建设方案详细.doc
  12. OpenCVSharp Mat.Set<T>修改像素颜色
  13. 红警2(红色警戒)之尤里的复仇 局域网对战联机方法
  14. 科目二边距30cm有什么技巧
  15. 枚举,如何定义一个枚举,枚举的本质
  16. Spring Data JPA 查询方法的命名语法与参数
  17. MIT6.824-lab2A-2022篇(万字推导思路及代码构建)
  18. set off 和 set out 的区别
  19. 码农老黄历-看今天哪个方位BUG最少
  20. scala之偏函数学习

热门文章

  1. 读spring源码(一)-ClassPathXmlApplicationContext-初始化
  2. 面向对象编程语言中的接口(Interface)
  3. 排序的几种方法 oc
  4. Arch linux
  5. Java并发基础02. 传统线程技术中的定时器技术
  6. 039_External Data Source(转载)
  7. 如何从管理IT服务提供商获得最大收益
  8. [20170412]bbed恢复修改记录(不等长).txt
  9. 时间轴CSS的Demo
  10. 更改chrome临时目录(可举一反三)