在之前文章的铺垫下,再为大家分享一篇:Android手势密码,附源码下载,不要错过。

源码下载:http://xiazai.jb51.net/201610/yuanma/androidLock(jb51.net).rar

先看第一张图片的布局文件

activity_main.xml

      

再看上面布局的java代码
MainActivity

package com.wujay.fund;  import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button;  public class MainActivity extends Activity implements OnClickListener {  private Button mBtnSetLock;  private Button mBtnVerifyLock;   @Override  protected void onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  setContentView(R.layout.activity_main);  setUpView();  setUpListener();  }   private void setUpView() {  mBtnSetLock = (Button) findViewById(R.id.btn_set_lockpattern);  mBtnVerifyLock = (Button) findViewById(R.id.btn_verify_lockpattern);  }   private void setUpListener() {  mBtnSetLock.setOnClickListener(this);  mBtnVerifyLock.setOnClickListener(this);  }   @Override  public void onClick(View v) {  switch (v.getId()) {  case R.id.btn_set_lockpattern:   startSetLockPattern();   break;  case R.id.btn_verify_lockpattern:   startVerifyLockPattern();   break;  default:   break;  }  }   private void startSetLockPattern() {  Intent intent = new Intent(MainActivity.this, GestureEditActivity.class);  startActivity(intent);  }   private void startVerifyLockPattern() {  Intent intent = new Intent(MainActivity.this, GestureVerifyActivity.class);  startActivity(intent);  } } 

另外看下工具类和bean类
AppUtil

package com.wujay.fund.common;  import android.content.Context; import android.view.WindowManager;  public class AppUtil {  public static int[] getScreenDispaly(Context context) {  WindowManager windowManager = (WindowManager) context   .getSystemService(Context.WINDOW_SERVICE);  int width = windowManager.getDefaultDisplay().getWidth();// 手机屏幕的宽度  int height = windowManager.getDefaultDisplay().getHeight();// 手机屏幕的高度  int result[] = { width, height };  return result;  } } 

再看9宫格的单位bean类
GesturePoint

package com.wujay.fund.entity;   import com.wujay.fund.R; import com.wujay.fund.common.Constants;  import android.widget.ImageView;  public class GesturePoint {  /**  * 状态值  */  private int pointState;   /** 代表这个Point对象代表的数字,从1开始(直接感觉从1开始)*/  private int num;  private int leftX;  private int rightX;  private int topY;  private int bottomY;  private ImageView image;   private int centerX;  private int centerY;  public GesturePoint(int leftX, int rightX, int topY, int bottomY,   ImageView image, int num) {  super();  this.leftX = leftX;  this.rightX = rightX;  this.topY = topY;  this.bottomY = bottomY;  this.image = image;   this.centerX = (leftX + rightX) / 2;  this.centerY = (topY + bottomY) / 2;   this.num = num;  }   public int getLeftX() {  return leftX;  }   public void setLeftX(int leftX) {  this.leftX = leftX;  }   public int getRightX() {  return rightX;  }   public void setRightX(int rightX) {  this.rightX = rightX;  }   public int getTopY() {  return topY;  }   public void setTopY(int topY) {  this.topY = topY;  }   public int getBottomY() {  return bottomY;  }   public void setBottomY(int bottomY) {  this.bottomY = bottomY;  }   public ImageView getImage() {  return image;  }   public void setImage(ImageView image) {  this.image = image;  }   public int getCenterX() {  return centerX;  }   public void setCenterX(int centerX) {  this.centerX = centerX;  }   public int getCenterY() {  return centerY;  }   public void setCenterY(int centerY) {  this.centerY = centerY;  }   public int getPointState() {  return pointState;  }   public void setPointState(int state) {  pointState = state;  switch (state) {  case Constants.POINT_STATE_NORMAL:   this.image.setBackgroundResource(R.drawable.gesture_node_normal);   break;  case Constants.POINT_STATE_SELECTED:   this.image.setBackgroundResource(R.drawable.gesture_node_pressed);   break;  case Constants.POINT_STATE_WRONG:   this.image.setBackgroundResource(R.drawable.gesture_node_wrong);   break;  default:   break;  }  }   public int getNum() {  return num;  }   public void setNum(int num) {  this.num = num;  }   @Override  public int hashCode() {  final int prime = 31;  int result = 1;  result = prime * result + bottomY;  result = prime * result + ((image == null) ? 0 : image.hashCode());  result = prime * result + leftX;  result = prime * result + rightX;  result = prime * result + topY;  return result;  }   @Override  public boolean equals(Object obj) {  if (this == obj)   return true;  if (obj == null)   return false;  if (getClass() != obj.getClass())   return false;  GesturePoint other = (GesturePoint) obj;  if (bottomY != other.bottomY)   return false;  if (image == null) {   if (other.image != null)   return false;  } else if (!image.equals(other.image))   return false;  if (leftX != other.leftX)   return false;  if (rightX != other.rightX)   return false;  if (topY != other.topY)   return false;  return true;  }   @Override  public String toString() {  return "Point [leftX=" + leftX + ", rightX=" + rightX + ", topY="   + topY + ", bottomY=" + bottomY + "]";  } } 

再看每个点位的3种状态
Constants

package com.wujay.fund.common; public class Constants { public static final int POINT_STATE_NORMAL = 0; // 正常状态 public static final int POINT_STATE_SELECTED = 1; // 按下状态 public static final int POINT_STATE_WRONG = 2; // 错误状态 } 

再看来绘制密码的界面
activity_gesture_edit.xml

                            

再看来绘制密码的类
GestureEditActivity

package com.wujay.fund;  import com.wujay.fund.R; import android.app.Activity; import android.os.Bundle; import android.text.Html; import android.text.TextUtils; 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.widget.GestureContentView; import com.wujay.fund.widget.GestureDrawline.GestureCallBack;  /**  * 手势密码设置界面  */ public class GestureEditActivity extends Activity implements OnClickListener {  // 2次绘制手势密码不正确的提示语  private TextView mTextTip;  // 手势密码绘制区域  private FrameLayout mGestureContainer;  private GestureContentView mGestureContentView;  // 重新设置手势密码  private TextView mTextReset;  // 是否是第一次绘制密码锁  private boolean mIsFirstInput = true;  // 初次绘制完毕密码锁,生成的密码  private String mFirstPassword = null;   @Override  public void onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  setContentView(R.layout.activity_gesture_edit);  setUpViews();  setUpListeners();  }   /**  * 判断初次绘制完毕生成的密码判断 判断是不是为空 判断密码数量是不是小于4  */  private boolean isInputPassValidate(String inputPassword) {  if (TextUtils.isEmpty(inputPassword) || inputPassword.length() < 4) {   return false;  }  return true;  }   private void setUpViews() {  // 重新设置手势密码  mTextReset = (TextView) findViewById(R.id.text_reset);  // 默认不可点击  mTextReset.setClickable(false);  // 2次绘制手势密码不正确的提示语  mTextTip = (TextView) findViewById(R.id.text_tip);  // 手势密码绘制区域  mGestureContainer = (FrameLayout) findViewById(R.id.gesture_container);  /**   * 初始化一个显示各个点的viewGroup GestureContentView(Context context, boolean   * isVerify, String passWord, GestureCallBack callBack)   */  mGestureContentView = new GestureContentView(this, false, "",   new GestureCallBack() {    @Override    public void onGestureCodeInput(String inputCode) {    // 验证输入的图案密码--如果密码为null。或者密码个数少于4个    if (!isInputPassValidate(inputCode)) {     mTextTip.setText(Html      .fromHtml("最少链接4个点, 请重新输入"));     // 立刻清楚画的线段     mGestureContentView.clearDrawlineState(0L);     return;    }    if (mIsFirstInput) {     // 第一次输入密码--保存第一次输入的密码,在进行跟第二次判断     mFirstPassword = 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("与上一次绘制不一致,请重新绘制"));     // 左右移动动画     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);  }   /*****************************************************/  private void setUpListeners() {  mTextReset.setOnClickListener(this);  }   @Override  public void onClick(View v) {  switch (v.getId()) {  case R.id.text_reset:   mIsFirstInput = true;   mTextTip.setText(getString(R.string.set_gesture_pattern));   break;  default:   break;  }  }  } 

GestureContentView

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;  /**  * 手势密码容器类  */ public class GestureContentView extends ViewGroup {  private GestureDrawline gestureDrawline;   /************************************************************************  * 包含9个ImageView的容器,初始化  *  * @param context  * @param isVerify  *  是否为校验手势密码  * @param passWord  *  用户传入密码  * @param callBack  *  手势绘制完毕的回调  */  private int[] screenDispaly;  // 将屏幕宽度分成3份  private int blockWidth;  // 9个点位的集合  private List list;  // 环境  private Context context;  // 是否需要校验密码  private boolean isVerify;   public GestureContentView(Context context, boolean isVerify,   String passWord, GestureCallBack callBack) {  super(context);  // 获取屏幕宽度  screenDispaly = AppUtil.getScreenDispaly(context);  // 获取屏幕宽度的1/3  blockWidth = screenDispaly[0] / 3;  this.list = new ArrayList();  this.context = context;  this.isVerify = isVerify;  // 添加9个图标  addChild();  // 初始化一个可以画线的view  gestureDrawline = new GestureDrawline(context, list, isVerify,   passWord, callBack);  }   /**  * 添加9个圆点的图标  */  // 用来计算2个圆心之间的一半距离大小  private int baseNum = 6;   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();   // 第几行---012 0 ,345 1, 678 2--   int row = i / 3;   // 第几列---012 012 , 345 012 , 678 012   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);   // 添加9个圆点图标   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);  }  } 

GestureDrawline

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;  /**  * 手势密码路径绘制  *  */ public class GestureDrawline extends View {  private int mov_x;// 声明起点坐标  private int mov_y;   private Map autoCheckPointMap;// 自动选中的情况点  private boolean isDrawEnable = true; // 是否允许绘制   /**********************************************************************  * 构造函数  */  private int[] screenDispaly;  private Paint paint;// 声明画笔  private Canvas canvas;// 画布  private Bitmap bitmap;// 位图  private List list;// 装有各个view坐标的集合  private List> lineList;// 记录画过的线  private StringBuilder passWordSb;  private boolean isVerify;  private String passWord;  private GestureCallBack callBack;   public GestureDrawline(Context context, List 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>();   initAutoCheckPointMap();  this.callBack = callBack;   // 初始化密码缓存  this.isVerify = isVerify;  this.passWordSb = new StringBuilder();  this.passWord = passWord;  }   private void initAutoCheckPointMap() {  autoCheckPointMap = new HashMap();  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) {  canvas.drawBitmap(bitmap, 0, 0, paint);   }   /**  * 通过点的位置去集合里面查找这个点是包含在哪个Point里面的  *  * @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 void clearScreenAndDrawList() {  canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);  for (Pair pair : lineList) {   // drawLine(float startX, float startY, float stopX, float stopY,   // Paint paint)   canvas.drawLine(pair.first.getCenterX(), pair.first.getCenterY(),    pair.second.getCenterX(), pair.second.getCenterY(), paint);// 画线  }  }   /**  * 判断是否中间点需要选中  *  * @param pointStart  * @param pointEnd  * @return  */  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 GesturePoint currentPoint;   @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:   // 鼠标按下后,获取手指点位的xy坐标   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());   }   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)) {   // 点击移动区域不在圆的区域,或者当前点击的点与当前移动到的点的位置相同   // 那么以当前的点中心为起点,以手指移动位置为终点画线   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 pair1 = new Pair(     currentPoint, betweenPoint);    lineList.add(pair1);    passWordSb.append(betweenPoint.getNum());    Pair pair2 = new Pair(     betweenPoint, pointAt);    lineList.add(pair2);    passWordSb.append(pointAt.getNum());    // 设置中间点选中    betweenPoint.setPointState(Constants.POINT_STATE_SELECTED);    // 赋值当前的point;    currentPoint = pointAt;   } else {    Pair pair = new Pair(     currentPoint, pointAt);    lineList.add(pair);    passWordSb.append(pointAt.getNum());    // 赋值当前的point;    currentPoint = pointAt;   }   }   invalidate();   break;  case MotionEvent.ACTION_UP:// 当手指抬起的时候   if (isVerify) {   // 手势密码校验   // 清掉屏幕上所有的线,只画上集合里面保存的线   if (passWord.equals(passWordSb.toString())) {    // 代表用户绘制的密码手势与传入的密码相同    callBack.checkedSuccess();   } else {    // 用户绘制的密码与传入的密码不同。    callBack.checkedFail();   }   } else {   callBack.onGestureCodeInput(passWordSb.toString());   }   break;  default:   break;  }  return true;  }   /************************************  * 校验错误/两次绘制不一致提示  */  private void drawErrorPathTip() {  canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);  paint.setColor(Color.rgb(154, 7, 21));// 设置默认线路颜色  for (Pair 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();  }   /**  * 指定时间去清除绘制的状态  *  * @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;  }  }   public interface GestureCallBack {   /**   * 用户设置/输入了手势密码   */  public abstract void onGestureCodeInput(String inputCode);   /**   * 代表用户绘制的密码与传入的密码相同   */  public abstract void checkedSuccess();   /**   * 代表用户绘制的密码与传入的密码不相同   */  public abstract void checkedFail();  }  } 

接下来看验证密码锁的布局
activity_gesture_verify.xml

                   

验证密码的代码实现类
GestureVerifyActivity

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{  private TextView mTextTip;  private FrameLayout mGestureContainer;  private GestureContentView mGestureContentView;   @Override  public void onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  setContentView(R.layout.activity_gesture_verify);  setUpViews();  }    private void setUpViews() {  //验证失败的错误提示  mTextTip = (TextView) findViewById(R.id.text_tip);  mGestureContainer = (FrameLayout) findViewById(R.id.gesture_container);    // 初始化一个显示各个点的viewGroup  mGestureContentView = new GestureContentView(this, true, "12589",   new GestureCallBack() {     @Override    public void onGestureCodeInput(String inputCode) {     }     @Override    public void checkedSuccess() {    mGestureContentView.clearDrawlineState(0L);    Toast.makeText(GestureVerifyActivity.this, "密码正确", 1000).show();    GestureVerifyActivity.this.finish();    }     @Override    public void checkedFail() {    mGestureContentView.clearDrawlineState(1300L);    mTextTip.setVisibility(View.VISIBLE);    mTextTip.setText(Html     .fromHtml("密码错误"));    // 左右移动动画    Animation shakeAnimation = AnimationUtils.loadAnimation(GestureVerifyActivity.this, R.anim.shake);    mTextTip.startAnimation(shakeAnimation);    }   });  // 设置手势解锁显示到哪个布局里面  mGestureContentView.setParentView(mGestureContainer);  }   } 

shake.xml

<?xml version="1.0" encoding="utf-8"?>  

推荐文章:

Android自定义UI手势密码简单版

Android自定义UI手势密码改进版

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

更多相关文章

  1. android手势事件 快速移动 长按触摸屏 按下触摸屏,并拖动
  2. Android之ViewFlipper的用法
  3. Android从2.2到8.0的源码
  4. Android(安卓)Studio编译报错:Password verification failed
  5. android 保存 用户名和密码 设置等应用信息优化
  6. 【Android】使用OpenCV提取人体肤色区域
  7. Android中定义Viewport需要注意的几个数字?
  8. sharedPreferences保存数据和TextWatcher监听输入框的技术介绍
  9. Android(安卓)设置EditText显示或隐藏密码

随机推荐

  1. android annotation配置及简单使用
  2. Android数据适配-ExpandableListView
  3. Android "无法查看***。请释放部分手机内
  4. 【小米招聘]】Android系统软件测试工程师
  5. 使用Jenkins自动构建Android问题总结
  6. 【Android Developers Training】 2. 运
  7. Android ViewPager+Fragment 实现画廊效
  8. android:自定义actionbar样式和布局
  9. 郭霖公众号的文章连接
  10. Android多线程分析之三:Handler,Looper的实