这几个月都是在做招財进宝项目。一个高收益低风险的理財APP,有兴趣的能够下载玩玩。收益不错哦!

招財进宝下载地址:http://8.shengpay.com/

前段时间因产品需求,做了一个手势password。跟支付宝的手势password类似,这里跟大家分享交流一下我实现的方式吧。

这篇来分享一下绘制手势password的实现(主要是设置手势password、校验手势password):

一、大致界面介绍:

                    

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd3VsaWFuZ2h1YW4=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" width="270" height="480" alt="">

图1                                                                                                                 图2

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd3VsaWFuZ2h1YW4=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" width="270" height="480" alt="">                     

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd3VsaWFuZ2h1YW4=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" width="270" height="480" alt="">

图3                                                                                                                图4

图1:手势password绘制界面 【主要是绘制上方的9个提示图标和9个宫格password图标】

图2:设置手势password 【监听手势的输入。TouchEvent的事件处理,获取输入的手势password,同一时候显示在上方的提示区域】

图3:再绘制一次。两次password不一致提示界面 【这里在实现的时候。错误提示文字加了“左右晃动的动画”,错误路径颜色标记为红色】

图4:校验手势password,输入的password错误,给予红色路径+错误文字提示

二、实现思路:

1. 正上方的提示区域,用一个类(LockIndicator.java)来实现。自己定义view来绘制9个提示图标;

2. 手势password绘制区域,用一个类(GestureContentView.java)来实现。它继承自ViewGroup里面, 加入9个ImageView来表示图标, 在onLayout()方法中设置它们的位置。

3. 手势路径绘制。 用一个类(GestureDrawline.java)来实现。复写onTouchEvent()方法,在这种方法里面监听TouchEvent事件: ACTION_DOWN、ACTION_MOVE、ACTION_UP事件,来绘制手势连接不同点之间的路径;

4. 9个点的对象,用一个类(GesturePoint.java)来实现,保存它的位置、状态、背景图片等相关信息。

5. 手势password的获取,推断手指当前的位置,依据滑动路径经过的点,按顺序保存绘制的点的顺序(这里的点顺序从上到下各自是:1,2,3,4,5,6,7,8,9)。不能有反复的点。

三、代码实现步骤:

1.要用一个类来表示这9个点中的第一个点。里面保留有当前点的上下左右的各个位置等属性

2.自己定义GroupView,用来装9个点,9个点的显示是通过ImageView。复写onLayout这种方法,让点按需求排列

3.定义一个能够画线的View,复写onTouchEvent方法,在这种方法里面进行画直线的操作

4.推断用户手指当前的位置。取出当前的位置去与那9个点中的每一个点的位置进行比較,假设用户点的位置在某一个点之内,那么当那个点置换背景图片。

详细实现代码例如以下:

1. LockIndicator.java 图案提示类

package com.snda.fund.widget;

import com.snda.fund.R;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.drawable.Drawable;
import android.os.PowerManager;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View; /**
*
* 手势password图案提示
* @author wulianghuan
*
*/
public class LockIndicator extends View {
private int numRow = 3; // 行
private int numColum = 3; // 列
private int patternWidth = 40;
private int patternHeight = 40;
private int f = 5;
private int g = 5;
private int strokeWidth = 3;
private Paint paint = null;
private Drawable patternNoraml = null;
private Drawable patternPressed = null;
private String lockPassStr; // 手势password public LockIndicator(Context paramContext) {
super(paramContext);
} public LockIndicator(Context paramContext, AttributeSet paramAttributeSet) {
super(paramContext, paramAttributeSet, 0);
paint = new Paint();
paint.setAntiAlias(true);
paint.setStrokeWidth(strokeWidth);
paint.setStyle(Paint.Style.STROKE);
patternNoraml = getResources().getDrawable(R.drawable.lock_pattern_node_normal);
patternPressed = getResources().getDrawable(R.drawable.lock_pattern_node_pressed);
if (patternPressed != null) {
patternWidth = patternPressed.getIntrinsicWidth();
patternHeight = patternPressed.getIntrinsicHeight();
this.f = (patternWidth / 4);
this.g = (patternHeight / 4);
patternPressed.setBounds(0, 0, patternWidth, patternHeight);
patternNoraml.setBounds(0, 0, patternWidth, patternHeight);
}
} @Override
protected void onDraw(Canvas canvas) {
if ((patternPressed == null) || (patternNoraml == null)) {
return;
}
// 绘制3*3的图标
for (int i = 0; i < numRow; i++) {
for (int j = 0; j < numColum; j++) {
paint.setColor(-16777216);
int i1 = j * patternHeight + j * this.g;
int i2 = i * patternWidth + i * this.f;
canvas.save();
canvas.translate(i1, i2);
String curNum = String.valueOf(numColum * i + (j + 1));
if (!TextUtils.isEmpty(lockPassStr)) {
if (lockPassStr.indexOf(curNum) == -1) {
// 未选中
patternNoraml.draw(canvas);
} else {
// 被选中
patternPressed.draw(canvas);
}
} else {
// 重置状态
patternNoraml.draw(canvas);
}
canvas.restore();
}
}
} @Override
protected void onMeasure(int paramInt1, int paramInt2) {
if (patternPressed != null)
setMeasuredDimension(numColum * patternHeight + this.g
* (-1 + numColum), numRow * patternWidth + this.f
* (-1 + numRow));
} /**
* 请求又一次绘制
* @param paramString 手势password字符序列
*/
public void setPath(String paramString) {
lockPassStr = paramString;
invalidate();
} }

2. GestureContentView.java  手势password容器类

它继承ViewGroup。通过addView()方法加入子viewe。手势password的9个输入点(GesturePoint)、GestureDrawline手势password路径都放在这个容器其中,以下是它的详细实现方法:

package com.wujay.fund.widget;

import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import com.wujay.fund.R;
import com.wujay.fund.common.AppUtil;
import com.wujay.fund.entity.GesturePoint;
import com.wujay.fund.widget.GestureDrawline.GestureCallBack; /**
* 手势password容器类
*
*/
public class GestureContentView extends ViewGroup { private int baseNum = 6; private int[] screenDispaly; /**
* 每一个点区域的宽度
*/
private int blockWidth;
/**
* 声明一个集合用来封装坐标集合
*/
private List<GesturePoint> list;
private Context context;
private boolean isVerify;
private GestureDrawline gestureDrawline; /**
* 包括9个ImageView的容器,初始化
* @param context
* @param isVerify 是否为校验手势password
* @param passWord 用户传入password
* @param callBack 手势绘制完成的回调
*/
public GestureContentView(Context context, boolean isVerify, String passWord, GestureCallBack callBack) {
super(context);
screenDispaly = AppUtil.getScreenDispaly(context);
blockWidth = screenDispaly[0]/3;
this.list = new ArrayList<GesturePoint>();
this.context = context;
this.isVerify = isVerify;
// 加入9个图标
addChild();
// 初始化一个能够画线的view
gestureDrawline = new GestureDrawline(context, list, isVerify, passWord, callBack);
} private void addChild(){
for (int i = 0; i < 9; i++) {
ImageView image = new ImageView(context);
image.setBackgroundResource(R.drawable.gesture_node_normal);
this.addView(image);
invalidate();
// 第几行
int row = i / 3;
// 第几列
int col = i % 3;
// 定义点的每一个属性
int leftX = col*blockWidth+blockWidth/baseNum;
int topY = row*blockWidth+blockWidth/baseNum;
int rightX = col*blockWidth+blockWidth-blockWidth/baseNum;
int bottomY = row*blockWidth+blockWidth-blockWidth/baseNum;
GesturePoint p = new GesturePoint(leftX, rightX, topY, bottomY, image,i+1);
this.list.add(p);
}
} public void setParentView(ViewGroup parent){
// 得到屏幕的宽度
int width = screenDispaly[0];
LayoutParams layoutParams = new LayoutParams(width, width);
this.setLayoutParams(layoutParams);
gestureDrawline.setLayoutParams(layoutParams);
parent.addView(gestureDrawline);
parent.addView(this);
} @Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
for (int i = 0; i < getChildCount(); i++) {
//第几行
int row = i/3;
//第几列
int col = i%3;
View v = getChildAt(i);
v.layout(col*blockWidth+blockWidth/baseNum, row*blockWidth+blockWidth/baseNum,
col*blockWidth+blockWidth-blockWidth/baseNum, row*blockWidth+blockWidth-blockWidth/baseNum);
}
} @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// 遍历设置每一个子view的大小
for (int i = 0; i < getChildCount(); i++) {
View v = getChildAt(i);
v.measure(widthMeasureSpec, heightMeasureSpec);
}
} /**
* 保留路径delayTime时间长
* @param delayTime
*/
public void clearDrawlineState(long delayTime) {
gestureDrawline.clearDrawlineState(delayTime);
} }

3. GestureDrawline.java 手势password路径绘制类

依据OnTouchEvent方法的不同事件,ACTION_DOWN、ACTION_MOVE、ACTION_UP分别处理不同的逻辑。

package com.wujay.fund.widget;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.wujay.fund.common.AppUtil;
import com.wujay.fund.common.Constants;
import com.wujay.fund.entity.GesturePoint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.PorterDuff;
import android.os.Handler;
import android.util.Log;
import android.util.Pair;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast; /**
* 手势password路径绘制
*
*/
public class GestureDrawline extends View {
private int mov_x;// 声明起点坐标
private int mov_y;
private Paint paint;// 声明画笔
private Canvas canvas;// 画布
private Bitmap bitmap;// 位图
private List<GesturePoint> list;// 装有各个view坐标的集合
private List<Pair<GesturePoint, GesturePoint>> lineList;// 记录画过的线
private Map<String, GesturePoint> autoCheckPointMap;// 自己主动选中的情况点
private boolean isDrawEnable = true; // 是否同意绘制 /**
* 屏幕的宽度和高度
*/
private int[] screenDispaly; /**
* 手指当前在哪个Point内
*/
private GesturePoint currentPoint;
/**
* 用户画图的回调
*/
private GestureCallBack callBack; /**
* 用户当前绘制的图形password
*/
private StringBuilder passWordSb; /**
* 是否为校验
*/
private boolean isVerify; /**
* 用户传入的passWord
*/
private String passWord; public GestureDrawline(Context context, List<GesturePoint> list, boolean isVerify,
String passWord, GestureCallBack callBack) {
super(context);
screenDispaly = AppUtil.getScreenDispaly(context);
paint = new Paint(Paint.DITHER_FLAG);// 创建一个画笔
bitmap = Bitmap.createBitmap(screenDispaly[0], screenDispaly[0], Bitmap.Config.ARGB_8888); // 设置位图的宽高
canvas = new Canvas();
canvas.setBitmap(bitmap);
paint.setStyle(Style.STROKE);// 设置非填充
paint.setStrokeWidth(10);// 笔宽5像素
paint.setColor(Color.rgb(245, 142, 33));// 设置默认连线颜色
paint.setAntiAlias(true);// 不显示锯齿 this.list = list;
this.lineList = new ArrayList<Pair<GesturePoint, GesturePoint>>(); initAutoCheckPointMap();
this.callBack = callBack; // 初始化password缓存
this.isVerify = isVerify;
this.passWordSb = new StringBuilder();
this.passWord = passWord;
} private void initAutoCheckPointMap() {
autoCheckPointMap = new HashMap<String,GesturePoint>();
autoCheckPointMap.put("1,3", getGesturePointByNum(2));
autoCheckPointMap.put("1,7", getGesturePointByNum(4));
autoCheckPointMap.put("1,9", getGesturePointByNum(5));
autoCheckPointMap.put("2,8", getGesturePointByNum(5));
autoCheckPointMap.put("3,7", getGesturePointByNum(5));
autoCheckPointMap.put("3,9", getGesturePointByNum(6));
autoCheckPointMap.put("4,6", getGesturePointByNum(5));
autoCheckPointMap.put("7,9", getGesturePointByNum(8));
} private GesturePoint getGesturePointByNum(int num) {
for (GesturePoint point : list) {
if (point.getNum() == num) {
return point;
}
}
return null;
} // 画位图
@Override
protected void onDraw(Canvas canvas) {
// super.onDraw(canvas);
canvas.drawBitmap(bitmap, 0, 0, null);
} // 触摸事件
@Override
public boolean onTouchEvent(MotionEvent event) {
if (isDrawEnable == false) {
// 当期不同意绘制
return true;
}
paint.setColor(Color.rgb(245, 142, 33));// 设置默认连线颜色
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mov_x = (int) event.getX();
mov_y = (int) event.getY();
// 推断当前点击的位置是处于哪个点之内
currentPoint = getPointAt(mov_x, mov_y);
if (currentPoint != null) {
currentPoint.setPointState(Constants.POINT_STATE_SELECTED);
passWordSb.append(currentPoint.getNum());
}
// canvas.drawPoint(mov_x, mov_y, paint);// 画点
invalidate();
break;
case MotionEvent.ACTION_MOVE:
clearScreenAndDrawList(); // 得到当前移动位置是处于哪个点内
GesturePoint pointAt = getPointAt((int) event.getX(), (int) event.getY());
// 代表当前用户手指处于点与点之前
if (currentPoint == null && pointAt == null) {
return true;
} else {// 代表用户的手指移动到了点上
if (currentPoint == null) {// 先推断当前的point是不是为null
// 假设为空,那么把手指移动到的点赋值给currentPoint
currentPoint = pointAt;
// 把currentPoint这个点设置选中为true;
currentPoint.setPointState(Constants.POINT_STATE_SELECTED);
passWordSb.append(currentPoint.getNum());
}
}
if (pointAt == null || currentPoint.equals(pointAt) || Constants.POINT_STATE_SELECTED == pointAt.getPointState()) {
// 点击移动区域不在圆的区域。或者当前点击的点与当前移动到的点的位置同样,或者当前点击的点处于选中状态
// 那么以当前的点中心为起点,以手指移动位置为终点画线
canvas.drawLine(currentPoint.getCenterX(), currentPoint.getCenterY(), event.getX(), event.getY(), paint);// 画线
} else {
// 假设当前点击的点与当前移动到的点的位置不同
// 那么曾经前点的中心为起点,以手移动到的点的位置画线
canvas.drawLine(currentPoint.getCenterX(), currentPoint.getCenterY(), pointAt.getCenterX(), pointAt.getCenterY(), paint);// 画线
pointAt.setPointState(Constants.POINT_STATE_SELECTED); // 推断是否中间点须要选中
GesturePoint betweenPoint = getBetweenCheckPoint(currentPoint, pointAt);
if (betweenPoint != null && Constants.POINT_STATE_SELECTED != betweenPoint.getPointState()) {
// 存在中间点而且没有被选中
Pair<GesturePoint, GesturePoint> pair1 = new Pair<GesturePoint, GesturePoint>(currentPoint, betweenPoint);
lineList.add(pair1);
passWordSb.append(betweenPoint.getNum());
Pair<GesturePoint, GesturePoint> pair2 = new Pair<GesturePoint, GesturePoint>(betweenPoint, pointAt);
lineList.add(pair2);
passWordSb.append(pointAt.getNum());
// 设置中间点选中
betweenPoint.setPointState(Constants.POINT_STATE_SELECTED);
// 赋值当前的point;
currentPoint = pointAt;
} else {
Pair<GesturePoint, GesturePoint> pair = new Pair<GesturePoint, GesturePoint>(currentPoint, pointAt);
lineList.add(pair);
passWordSb.append(pointAt.getNum());
// 赋值当前的point;
currentPoint = pointAt;
}
}
invalidate();
break;
case MotionEvent.ACTION_UP:// 当手指抬起的时候
if (isVerify) {
// 手势password校验
// 清掉屏幕上全部的线,仅仅画上集合里面保存的线
if (passWord.equals(passWordSb.toString())) {
// 代表用户绘制的password手势与传入的password同样
callBack.checkedSuccess();
} else {
// 用户绘制的password与传入的password不同。
callBack.checkedFail();
}
} else {
callBack.onGestureCodeInput(passWordSb.toString());
}
break;
default:
break;
}
return true;
} /**
* 指定时间去清除绘制的状态
* @param delayTime 延迟运行时间
*/
public void clearDrawlineState(long delayTime) {
if (delayTime > 0) {
// 绘制红色提示路线
isDrawEnable = false;
drawErrorPathTip();
}
new Handler().postDelayed(new clearStateRunnable(), delayTime);
} /**
* 清除绘制状态的线程
*/
final class clearStateRunnable implements Runnable {
public void run() {
// 重置passWordSb
passWordSb = new StringBuilder();
// 清空保存点的集合
lineList.clear();
// 又一次绘制界面
clearScreenAndDrawList();
for (GesturePoint p : list) {
p.setPointState(Constants.POINT_STATE_NORMAL);
}
invalidate();
isDrawEnable = true;
}
} /**
* 通过点的位置去集合里面查找这个点是包括在哪个Point里面的
*
* @param x
* @param y
* @return 假设没有找到,则返回null。代表用户当前移动的地方属于点与点之间
*/
private GesturePoint getPointAt(int x, int y) { for (GesturePoint point : list) {
// 先推断x
int leftX = point.getLeftX();
int rightX = point.getRightX();
if (!(x >= leftX && x < rightX)) {
// 假设为假。则跳到下一个对照
continue;
} int topY = point.getTopY();
int bottomY = point.getBottomY();
if (!(y >= topY && y < bottomY)) {
// 假设为假。则跳到下一个对照
continue;
} // 假设运行到这,那么说明当前点击的点的位置在遍历到点的位置这个地方
return point;
} return null;
} private GesturePoint getBetweenCheckPoint(GesturePoint pointStart, GesturePoint pointEnd) {
int startNum = pointStart.getNum();
int endNum = pointEnd.getNum();
String key = null;
if (startNum < endNum) {
key = startNum + "," + endNum;
} else {
key = endNum + "," + startNum;
}
return autoCheckPointMap.get(key);
} /**
* 清掉屏幕上全部的线。然后画出集合里面的线
*/
private void clearScreenAndDrawList() {
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
for (Pair<GesturePoint, GesturePoint> pair : lineList) {
canvas.drawLine(pair.first.getCenterX(), pair.first.getCenterY(),
pair.second.getCenterX(), pair.second.getCenterY(), paint);// 画线
}
} /**
* 校验错误/两次绘制不一致提示
*/
private void drawErrorPathTip() {
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
paint.setColor(Color.rgb(154, 7, 21));// 设置默认线路颜色
for (Pair<GesturePoint, GesturePoint> pair : lineList) {
pair.first.setPointState(Constants.POINT_STATE_WRONG);
pair.second.setPointState(Constants.POINT_STATE_WRONG);
canvas.drawLine(pair.first.getCenterX(), pair.first.getCenterY(),
pair.second.getCenterX(), pair.second.getCenterY(), paint);// 画线
}
invalidate();
} public interface GestureCallBack { /**
* 用户设置/输入了手势password
*/
public abstract void onGestureCodeInput(String inputCode); /**
* 代表用户绘制的password与传入的password同样
*/
public abstract void checkedSuccess(); /**
* 代表用户绘制的password与传入的password不同样
*/
public abstract void checkedFail();
} }

4.GestureEditActivity.java 手势password设置界面

手势password设置

代码例如以下:

package com.wujay.fund;

import com.wujay.fund.R;
import android.app.Activity;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.text.Html;
import android.text.TextUtils;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.FrameLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.wujay.fund.common.Constants;
import com.wujay.fund.widget.GestureContentView;
import com.wujay.fund.widget.GestureDrawline.GestureCallBack;
import com.wujay.fund.widget.LockIndicator; /**
*
* 手势password设置界面
*
*/
public class GestureEditActivity extends Activity implements OnClickListener {
/** 手机号码*/
public static final String PARAM_PHONE_NUMBER = "PARAM_PHONE_NUMBER";
/** 意图 */
public static final String PARAM_INTENT_CODE = "PARAM_INTENT_CODE";
/** 首次提示绘制手势password。能够选择跳过 */
public static final String PARAM_IS_FIRST_ADVICE = "PARAM_IS_FIRST_ADVICE";
private TextView mTextTitle;
private TextView mTextCancel;
private LockIndicator mLockIndicator;
private TextView mTextTip;
private FrameLayout mGestureContainer;
private GestureContentView mGestureContentView;
private TextView mTextReset;
private String mParamSetUpcode = null;
private String mParamPhoneNumber;
private boolean mIsFirstInput = true;
private String mFirstPassword = null;
private String mConfirmPassword = null;
private int mParamIntentCode; @Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_gesture_edit);
setUpViews();
setUpListeners();
} private void setUpViews() {
mTextTitle = (TextView) findViewById(R.id.text_title);
mTextCancel = (TextView) findViewById(R.id.text_cancel);
mTextReset = (TextView) findViewById(R.id.text_reset);
mTextReset.setClickable(false);
mLockIndicator = (LockIndicator) findViewById(R.id.lock_indicator);
mTextTip = (TextView) findViewById(R.id.text_tip);
mGestureContainer = (FrameLayout) findViewById(R.id.gesture_container);
// 初始化一个显示各个点的viewGroup
mGestureContentView = new GestureContentView(this, false, "", new GestureCallBack() {
@Override
public void onGestureCodeInput(String inputCode) {
if (!isInputPassValidate(inputCode)) {
mTextTip.setText(Html.fromHtml("<font color='#c70c1e'>最少链接4个点, 请又一次输入</font>"));
mGestureContentView.clearDrawlineState(0L);
return;
}
if (mIsFirstInput) {
mFirstPassword = inputCode;
updateCodeList(inputCode);
mGestureContentView.clearDrawlineState(0L);
mTextReset.setClickable(true);
mTextReset.setText(getString(R.string.reset_gesture_code));
} else {
if (inputCode.equals(mFirstPassword)) {
Toast.makeText(GestureEditActivity.this, "设置成功", Toast.LENGTH_SHORT).show();
mGestureContentView.clearDrawlineState(0L);
GestureEditActivity.this.finish();
} else {
mTextTip.setText(Html.fromHtml("<font color='#c70c1e'>与上一次绘制不一致。请又一次绘制</font>"));
// 左右移动动画
Animation shakeAnimation = AnimationUtils.loadAnimation(GestureEditActivity.this, R.anim.shake);
mTextTip.startAnimation(shakeAnimation);
// 保持绘制的线。1.5秒后清除
mGestureContentView.clearDrawlineState(1300L);
}
}
mIsFirstInput = false;
} @Override
public void checkedSuccess() { } @Override
public void checkedFail() { }
});
// 设置手势解锁显示到哪个布局里面
mGestureContentView.setParentView(mGestureContainer);
updateCodeList("");
} private void setUpListeners() {
mTextCancel.setOnClickListener(this);
mTextReset.setOnClickListener(this);
} private void updateCodeList(String inputCode) {
// 更新选择的图案
mLockIndicator.setPath(inputCode);
} @Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.text_cancel:
this.finish();
break;
case R.id.text_reset:
mIsFirstInput = true;
updateCodeList("");
mTextTip.setText(getString(R.string.set_gesture_pattern));
break;
default:
break;
}
} private boolean isInputPassValidate(String inputPassword) {
if (TextUtils.isEmpty(inputPassword) || inputPassword.length() < 4) {
return false;
}
return true;
} }

5. GestureVerifyActivity.java 手势password校验界面

代码例如以下:

package com.wujay.fund;

import com.wujay.fund.R;
import com.wujay.fund.widget.GestureContentView;
import com.wujay.fund.widget.GestureDrawline.GestureCallBack;
import android.app.Activity;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.os.Bundle;
import android.text.Html;
import android.text.TextUtils;
import android.view.KeyEvent;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast; /**
*
* 手势绘制/校验界面
*
*/
public class GestureVerifyActivity extends Activity implements android.view.View.OnClickListener {
/** 手机号码*/
public static final String PARAM_PHONE_NUMBER = "PARAM_PHONE_NUMBER";
/** 意图 */
public static final String PARAM_INTENT_CODE = "PARAM_INTENT_CODE";
private RelativeLayout mTopLayout;
private TextView mTextTitle;
private TextView mTextCancel;
private ImageView mImgUserLogo;
private TextView mTextPhoneNumber;
private TextView mTextTip;
private FrameLayout mGestureContainer;
private GestureContentView mGestureContentView;
private TextView mTextForget;
private TextView mTextOther;
private String mParamPhoneNumber;
private long mExitTime = 0;
private int mParamIntentCode; @Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_gesture_verify);
ObtainExtraData();
setUpViews();
setUpListeners();
} private void ObtainExtraData() {
mParamPhoneNumber = getIntent().getStringExtra(PARAM_PHONE_NUMBER);
mParamIntentCode = getIntent().getIntExtra(PARAM_INTENT_CODE, 0);
} private void setUpViews() {
mTopLayout = (RelativeLayout) findViewById(R.id.top_layout);
mTextTitle = (TextView) findViewById(R.id.text_title);
mTextCancel = (TextView) findViewById(R.id.text_cancel);
mImgUserLogo = (ImageView) findViewById(R.id.user_logo);
mTextPhoneNumber = (TextView) findViewById(R.id.text_phone_number);
mTextTip = (TextView) findViewById(R.id.text_tip);
mGestureContainer = (FrameLayout) findViewById(R.id.gesture_container);
mTextForget = (TextView) findViewById(R.id.text_forget_gesture);
mTextOther = (TextView) findViewById(R.id.text_other_account); // 初始化一个显示各个点的viewGroup
mGestureContentView = new GestureContentView(this, true, "1235789",
new GestureCallBack() { @Override
public void onGestureCodeInput(String inputCode) { } @Override
public void checkedSuccess() {
mGestureContentView.clearDrawlineState(0L);
Toast.makeText(GestureVerifyActivity.this, "password正确", 1000).show();
GestureVerifyActivity.this.finish();
} @Override
public void checkedFail() {
mGestureContentView.clearDrawlineState(1300L);
mTextTip.setVisibility(View.VISIBLE);
mTextTip.setText(Html
.fromHtml("<font color='#c70c1e'>password错误</font>"));
// 左右移动动画
Animation shakeAnimation = AnimationUtils.loadAnimation(GestureVerifyActivity.this, R.anim.shake);
mTextTip.startAnimation(shakeAnimation);
}
});
// 设置手势解锁显示到哪个布局里面
mGestureContentView.setParentView(mGestureContainer);
} private void setUpListeners() {
mTextCancel.setOnClickListener(this);
mTextForget.setOnClickListener(this);
mTextOther.setOnClickListener(this);
} private String getProtectedMobile(String phoneNumber) {
if (TextUtils.isEmpty(phoneNumber) || phoneNumber.length() < 11) {
return "";
}
StringBuilder builder = new StringBuilder();
builder.append(phoneNumber.subSequence(0,3));
builder.append("****");
builder.append(phoneNumber.subSequence(7,11));
return builder.toString();
} @Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.text_cancel:
this.finish();
break;
default:
break;
}
} }

以上是手势password实现的关键代码,我把项目中的模块代码整理出来,新建了一个project,供大家分享和交流

源代码下载地址:

源代码下载地址:http://download.csdn.net/detail/wulianghuan/8115995

Android招財进宝手势password的实现的更多相关文章

  1. Android 支付宝钱包手势password裂纹战斗

    底 随着移动互联网和手机屏幕越做越大的普及等..购物在移动设备上.消费是必不可少的人们习惯于生活. 随着这股浪潮的兴起,安全.便捷的移动支付的需求也越来越大.故,各大互联网公司纷纷推出了移动支付平台. ...

  2. 支付宝钱包手势password破解实战(root过的手机可直接绕过手势password)

    /* 本文章由 莫灰灰 编写,转载请注明出处. 作者:莫灰灰    邮箱: minzhenfei@163.com */ 背景 随着移动互联网的普及以及手机屏幕越做越大等特点,在移动设备上购物.消费已是 ...

  3. Android中仿淘宝首页顶部滚动自定义HorizontalScrollView定时水平自动切换图片

    Android中仿淘宝首页顶部滚动自定义HorizontalScrollView定时水平自动切换图片 自定义ADPager 自定义水平滚动的ScrollView效仿ViewPager 当遇到要在Vie ...

  4. android学习笔记51——SQLite 手势Gesture

    手势Gesture 所谓手势,是指用户手指或触摸笔在触摸屏幕上的连续触碰行为. Androi对两种手势行为都提供了支持: 1.对于第一种手势而言,android提供了手势检测,并为手势检测提供了相应的 ...

  5. 【原创】窥视懒人的秘密---android下拉刷新开启手势的新纪元

    小飒的成长史原创作品:窥视懒人的秘密---android下拉刷新开启手势的新纪元转载请注明出处 **************************************************** ...

  6. Android OnGestureListener用法 识别用户手势 左右滑动

    Android可以识别用户的手势(即用户用手指滑动的方向),通过用户不同的手势,从而做出不同的处理 需要使用OnGestureListener 比如说看电子书的时候翻页,或者要滑动一些其他内容 直接上 ...

  7. Android开发案例 - 淘宝商品详情

    所有电商APP的商品详情页面几乎都是和淘宝的一模一样(见下图): 采用上下分页的模式 商品基本参数 & 选购参数在上页展示 商品图文详情等其他信息放在下页展示 知识要点 垂直方向的ViewPa ...

  8. Android开发案例 - 淘宝商品详情【转】

    http://erehmi.cnblogs.com/ 所有电商APP的商品详情页面几乎都是和淘宝的一模一样(见下图): 采用上下分页的模式 商品基本参数 & 选购参数在上页展示 商品图文详情等 ...

  9. android 添加左右滑屏手势

    今天要在自己的项目中添加左右滑动,实现日期的加减(原来已经做了加减按键).滑动在一个中间的layout中进行 思路:添加左右划屏幕判断,得到判断后模拟加减按键按下. 模拟按键按下用 mbotton.p ...

随机推荐

  1. vue实现多语言国际化(vue-i18n),结合element ui、vue-router、echarts以及joint等。

    老板说我们的项目要和国际接轨,于是乎,加上了多语言(vue-i18n).项目用到的UI框架是element ui ,后续echarts.joint等全都得加上多语言. 一.言归正传,i18n在vue项 ...

  2. nuxt按需引入 element-UI、自定义主题色(终极按需引入)

    首先你要知道 nuxt.js怎么引入第三方插件 : 不多BB. 一.按需引入element-UI 第一步:安装 babel-plugin-component: npm install babel-pl ...

  3. 关于CSDN2013博客之星的一些看法

    最近一个周,最火的话题当然要数CSDN2013博客之星拉票了. 实话实说,从12月14日开始,我连续5天拉票. 通过QQ群.QQ好友.CSDN文章.给CSDN粉丝发私信等多种方式拉票,真是累死我了. ...

  4. 鲁德http://www.testroad.org/topic/76

     [最新的招聘信息]:1.联动优势科技有限公司招聘性能测试工程师       薪资20K左右 http://ask.testroad.org/article/4042.上海-交通银行总行-性能测试专家 ...

  5. boost 库编译选项

    boost大部分库仅仅须要包括头文件就可以使用,而有部分须要编译的.例如以下: E:\Qt\Qt3rdlib\boost_1_58_0>bjam --show-libraries The fol ...

  6. 【例题5-9 UVA - 1592】Database

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 枚举不同的列是哪两个列,然后枚举行. 把那一行的这两列的字符接在一起,然后用map判重. 为了防止逐个比较字符. 可以一开始先把字符 ...

  7. PostgreSQL 序列

    PostgreSQL 中的序列是一个数据库对象,本质上是一个自增器.因此,序列在其他同类型数据库软件中以 autoincrment 值的形式存在.在一张表需要非随机,唯一标实符的场景下,Sequenc ...

  8. 格式化上下文formatting contexts

    原文 简书原文:https://www.jianshu.com/p/20c32c367b63 什么是格式化上下文(formatting contexts) Formatting context是W3C ...

  9. 7、linux系统2440开发板域名解析问题

    如果在linux系统中ping某一台电脑的ip地址可以ping 通: ~ >: ping 192.168.1.3PING 192.168.1.3 (192.168.1.3): 56 data b ...

  10. FireBreath与JS交互1

    FireBreath提供接口供JS调用,提供的接口需要注册 必须在JSAPI对象的构造函数中注册,也就是 CxxxAPI::CxxxAPI()这个函数中调用 registerMethod(" ...