Android类似360的轨迹加密功能

jopen 12年前

最近做个东西,要用到这个所以发了下,希望能对大家有帮助,先上图:

主要实现:

1.自定义View LocusPassWordView

package com.huangcheng.lock;    import java.util.ArrayList;  import java.util.List;  import java.util.Timer;  import java.util.TimerTask;    import com.huangcheng.lock.util.BitmapUtil;  import com.huangcheng.lock.util.MathUtil;  import com.huangcheng.lock.util.RoundUtil;  import com.huangcheng.lock.util.StringUtil;    import android.content.Context;  import android.content.SharedPreferences;  import android.content.SharedPreferences.Editor;  import android.graphics.Bitmap;  import android.graphics.BitmapFactory;  import android.graphics.Canvas;  import android.graphics.Matrix;  import android.graphics.Paint;  import android.util.AttributeSet;  import android.util.Log;  import android.view.MotionEvent;  import android.view.View;  import android.widget.Toast;    /**   *    * 轨迹密码   *    * @author Dell   *    */  public class LocusPassWordView extends View {   private float w = 0;   private float h = 0;     //   private boolean isCache = false;   //   private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);     //   private Point[][] mPoints = new Point[3][3];   // 圆的半径   private float r = 0;   // 选中的点   private List<Point> sPoints = new ArrayList<Point>();   private boolean checking = false;   private Bitmap locus_round_original;   private Bitmap locus_round_click;   private Bitmap locus_round_click_error;   private Bitmap locus_line;   private Bitmap locus_line_semicircle;   private Bitmap locus_line_semicircle_error;   private Bitmap locus_arrow;   private Bitmap locus_line_error;   private long CLEAR_TIME = 800;   private int passwordMinLength = 5;   private boolean isTouch = true; // 是否可操作   private Matrix mMatrix = new Matrix();   private int lineAlpha = 100;     public LocusPassWordView(Context context, AttributeSet attrs, int defStyle) {    super(context, attrs, defStyle);   }     public LocusPassWordView(Context context, AttributeSet attrs) {    super(context, attrs);   }     public LocusPassWordView(Context context) {    super(context);   }     @Override   public void onDraw(Canvas canvas) {    if (!isCache) {     initCache();    }    drawToCanvas(canvas);   }     private void drawToCanvas(Canvas canvas) {      // mPaint.setColor(Color.RED);    // Point p1 = mPoints[1][1];    // Rect r1 = new Rect(p1.x - r,p1.y - r,p1.x +    // locus_round_click.getWidth() - r,p1.y+locus_round_click.getHeight()-    // r);    // canvas.drawRect(r1, mPaint);    // 画所有点    for (int i = 0; i < mPoints.length; i++) {     for (int j = 0; j < mPoints[i].length; j++) {      Point p = mPoints[i][j];      if (p.state == Point.STATE_CHECK) {       canvas.drawBitmap(locus_round_click, p.x - r, p.y - r,         mPaint);      } else if (p.state == Point.STATE_CHECK_ERROR) {       canvas.drawBitmap(locus_round_click_error, p.x - r,         p.y - r, mPaint);      } else {       canvas.drawBitmap(locus_round_original, p.x - r, p.y - r,         mPaint);      }     }    }    // mPaint.setColor(Color.BLUE);    // canvas.drawLine(r1.left+r1.width()/2, r1.top, r1.left+r1.width()/2,    // r1.bottom, mPaint);    // canvas.drawLine(r1.left, r1.top+r1.height()/2, r1.right,    // r1.bottom-r1.height()/2, mPaint);      // 画连线    if (sPoints.size() > 0) {     int tmpAlpha = mPaint.getAlpha();     mPaint.setAlpha(lineAlpha);     Point tp = sPoints.get(0);     for (int i = 1; i < sPoints.size(); i++) {      Point p = sPoints.get(i);      drawLine(canvas, tp, p);      tp = p;     }     if (this.movingNoPoint) {      drawLine(canvas, tp, new Point((int) moveingX, (int) moveingY));     }     mPaint.setAlpha(tmpAlpha);     lineAlpha = mPaint.getAlpha();    }     }     /**    * 初始化Cache信息    *     * @param canvas    */   private void initCache() {      w = this.getWidth();    h = this.getHeight();    float x = 0;    float y = 0;      // 以最小的为准    // 纵屏    if (w > h) {     x = (w - h) / 2;     w = h;    }    // 横屏    else {     y = (h - w) / 2;     h = w;    }      locus_round_original = BitmapFactory.decodeResource(      this.getResources(), R.drawable.locus_round_original);    locus_round_click = BitmapFactory.decodeResource(this.getResources(),      R.drawable.locus_round_click);    locus_round_click_error = BitmapFactory.decodeResource(      this.getResources(), R.drawable.locus_round_click_error);      locus_line = BitmapFactory.decodeResource(this.getResources(),      R.drawable.locus_line);    locus_line_semicircle = BitmapFactory.decodeResource(      this.getResources(), R.drawable.locus_line_semicircle);      locus_line_error = BitmapFactory.decodeResource(this.getResources(),      R.drawable.locus_line_error);    locus_line_semicircle_error = BitmapFactory.decodeResource(      this.getResources(), R.drawable.locus_line_semicircle_error);      locus_arrow = BitmapFactory.decodeResource(this.getResources(),      R.drawable.locus_arrow);    // Log.d("Canvas w h :", "w:" + w + " h:" + h);      // 计算圆圈图片的大小    float canvasMinW = w;    if (w > h) {     canvasMinW = h;    }    float roundMinW = canvasMinW / 8.0f * 2;    float roundW = roundMinW / 2.f;    //    float deviation = canvasMinW % (8 * 2) / 2;    x += deviation;    x += deviation;      if (locus_round_original.getWidth() > roundMinW) {     float sf = roundMinW * 1.0f / locus_round_original.getWidth(); // 取得缩放比例,将所有的图片进行缩放     locus_round_original = BitmapUtil.zoom(locus_round_original, sf);     locus_round_click = BitmapUtil.zoom(locus_round_click, sf);     locus_round_click_error = BitmapUtil.zoom(locus_round_click_error,       sf);       locus_line = BitmapUtil.zoom(locus_line, sf);     locus_line_semicircle = BitmapUtil.zoom(locus_line_semicircle, sf);       locus_line_error = BitmapUtil.zoom(locus_line_error, sf);     locus_line_semicircle_error = BitmapUtil.zoom(       locus_line_semicircle_error, sf);     locus_arrow = BitmapUtil.zoom(locus_arrow, sf);     roundW = locus_round_original.getWidth() / 2;    }      mPoints[0][0] = new Point(x + 0 + roundW, y + 0 + roundW);    mPoints[0][1] = new Point(x + w / 2, y + 0 + roundW);    mPoints[0][2] = new Point(x + w - roundW, y + 0 + roundW);    mPoints[1][0] = new Point(x + 0 + roundW, y + h / 2);    mPoints[1][1] = new Point(x + w / 2, y + h / 2);    mPoints[1][2] = new Point(x + w - roundW, y + h / 2);    mPoints[2][0] = new Point(x + 0 + roundW, y + h - roundW);    mPoints[2][1] = new Point(x + w / 2, y + h - roundW);    mPoints[2][2] = new Point(x + w - roundW, y + h - roundW);    int k = 0;    for (Point[] ps : mPoints) {     for (Point p : ps) {      p.index = k;      k++;     }    }    r = locus_round_original.getHeight() / 2;// roundW;    isCache = true;   }     /**    * 画两点的连接    *     * @param canvas    * @param a    * @param b    */   private void drawLine(Canvas canvas, Point a, Point b) {    float ah = (float) MathUtil.distance(a.x, a.y, b.x, b.y);    float degrees = getDegrees(a, b);    // Log.d("=============x===========", "rotate:" + degrees);    canvas.rotate(degrees, a.x, a.y);      if (a.state == Point.STATE_CHECK_ERROR) {     mMatrix.setScale((ah - locus_line_semicircle_error.getWidth())       / locus_line_error.getWidth(), 1);     mMatrix.postTranslate(a.x, a.y - locus_line_error.getHeight()       / 2.0f);     canvas.drawBitmap(locus_line_error, mMatrix, mPaint);     canvas.drawBitmap(locus_line_semicircle_error, a.x       + locus_line_error.getWidth(),       a.y - locus_line_error.getHeight() / 2.0f, mPaint);    } else {     mMatrix.setScale((ah - locus_line_semicircle.getWidth())       / locus_line.getWidth(), 1);     mMatrix.postTranslate(a.x, a.y - locus_line.getHeight() / 2.0f);     canvas.drawBitmap(locus_line, mMatrix, mPaint);     canvas.drawBitmap(locus_line_semicircle, a.x + ah       - locus_line_semicircle.getWidth(),       a.y - locus_line.getHeight() / 2.0f, mPaint);    }      canvas.drawBitmap(locus_arrow, a.x, a.y - locus_arrow.getHeight()      / 2.0f, mPaint);      canvas.rotate(-degrees, a.x, a.y);     }     public float getDegrees(Point a, Point b) {    float ax = a.x;// a.index % 3;    float ay = a.y;// a.index / 3;    float bx = b.x;// b.index % 3;    float by = b.y;// b.index / 3;    float degrees = 0;    if (bx == ax) // y轴相等 90度或270    {     if (by > ay) // 在y轴的下边 90     {      degrees = 90;     } else if (by < ay) // 在y轴的上边 270     {      degrees = 270;     }    } else if (by == ay) // y轴相等 0度或180    {     if (bx > ax) // 在y轴的下边 90     {      degrees = 0;     } else if (bx < ax) // 在y轴的上边 270     {      degrees = 180;     }    } else {     if (bx > ax) // 在y轴的右边 270~90     {      if (by > ay) // 在y轴的下边 0 - 90      {       degrees = 0;       degrees = degrees         + switchDegrees(Math.abs(by - ay),           Math.abs(bx - ax));      } else if (by < ay) // 在y轴的上边 270~0      {       degrees = 360;       degrees = degrees         - switchDegrees(Math.abs(by - ay),           Math.abs(bx - ax));      }       } else if (bx < ax) // 在y轴的左边 90~270     {      if (by > ay) // 在y轴的下边 180 ~ 270      {       degrees = 90;       degrees = degrees         + switchDegrees(Math.abs(bx - ax),           Math.abs(by - ay));      } else if (by < ay) // 在y轴的上边 90 ~ 180      {       degrees = 270;       degrees = degrees         - switchDegrees(Math.abs(bx - ax),           Math.abs(by - ay));      }       }      }    return degrees;   }     /**    * 1=30度 2=45度 4=60度    *     * @param tan    * @return    */   private float switchDegrees(float x, float y) {    return (float) MathUtil.pointTotoDegrees(x, y);   }     /**    * 取得数组下标    *     * @param index    * @return    */   public int[] getArrayIndex(int index) {    int[] ai = new int[2];    ai[0] = index / 3;    ai[1] = index % 3;    return ai;   }     /**    *     * 检查    *     * @param x    * @param y    * @return    */   private Point checkSelectPoint(float x, float y) {    for (int i = 0; i < mPoints.length; i++) {     for (int j = 0; j < mPoints[i].length; j++) {      Point p = mPoints[i][j];      if (RoundUtil.checkInRound(p.x, p.y, r, (int) x, (int) y)) {       return p;      }     }    }    return null;   }     /**    * 重置    */   private void reset() {    for (Point p : sPoints) {     p.state = Point.STATE_NORMAL;    }    sPoints.clear();    this.enableTouch();   }     /**    * 判断点是否有交叉 返回 0,新点 ,1 与上一点重叠 2,与非最后一点重叠    *     * @param p    * @return    */   private int crossPoint(Point p) {    // 重叠的不最后一个则 reset    if (sPoints.contains(p)) {     if (sPoints.size() > 2) {      // 与非最后一点重叠      if (sPoints.get(sPoints.size() - 1).index != p.index) {       return 2;      }     }     return 1; // 与最后一点重叠    } else {     return 0; // 新点    }   }     /**    * 添加一个点    *     * @param point    */   private void addPoint(Point point) {    this.sPoints.add(point);   }     /**    * 转换为String    *     * @param points    * @return    */   private String toPointString() {    if (sPoints.size() > passwordMinLength) {     StringBuffer sf = new StringBuffer();     for (Point p : sPoints) {      sf.append(",");      sf.append(p.index);     }     return sf.deleteCharAt(0).toString();    } else {     return "";    }   }     boolean movingNoPoint = false;   float moveingX, moveingY;     @Override   public boolean onTouchEvent(MotionEvent event) {    // 不可操作    if (!isTouch) {     return false;    }      movingNoPoint = false;      float ex = event.getX();    float ey = event.getY();    boolean isFinish = false;    boolean redraw = false;    Point p = null;    switch (event.getAction()) {    case MotionEvent.ACTION_DOWN: // 点下     // 如果正在清除密码,则取消     if (task != null) {      task.cancel();      task = null;      Log.d("task", "touch cancel()");     }     // 删除之前的点     reset();     p = checkSelectPoint(ex, ey);     if (p != null) {      checking = true;     }     break;    case MotionEvent.ACTION_MOVE: // 移动     if (checking) {      p = checkSelectPoint(ex, ey);      if (p == null) {       movingNoPoint = true;       moveingX = ex;       moveingY = ey;      }     }     break;    case MotionEvent.ACTION_UP: // 提起     p = checkSelectPoint(ex, ey);     checking = false;     isFinish = true;     break;    }    if (!isFinish && checking && p != null) {       int rk = crossPoint(p);     if (rk == 2) // 与非最后一重叠     {      // reset();      // checking = false;        movingNoPoint = true;      moveingX = ex;      moveingY = ey;        redraw = true;     } else if (rk == 0) // 一个新点     {      p.state = Point.STATE_CHECK;      addPoint(p);      redraw = true;     }     // rk == 1 不处理      }      // 是否重画    if (redraw) {      }    if (isFinish) {     if (this.sPoints.size() == 1) {      this.reset();     } else if (this.sPoints.size() < passwordMinLength       && this.sPoints.size() > 0) {      // mCompleteListener.onPasswordTooMin(sPoints.size());      error();      clearPassword();      Toast.makeText(this.getContext(), "密码太短,请重新输入!",        Toast.LENGTH_SHORT).show();     } else if (mCompleteListener != null) {      if (this.sPoints.size() >= passwordMinLength) {       this.disableTouch();       mCompleteListener.onComplete(toPointString());      }       }    }    this.postInvalidate();    return true;   }     /**    * 设置已经选中的为错误    */   private void error() {    for (Point p : sPoints) {     p.state = Point.STATE_CHECK_ERROR;    }   }     /**    * 设置为输入错误    */   public void markError() {    markError(CLEAR_TIME);   }     /**    * 设置为输入错误    */   public void markError(final long time) {    for (Point p : sPoints) {     p.state = Point.STATE_CHECK_ERROR;    }    this.clearPassword(time);   }     /**    * 设置为可操作    */   public void enableTouch() {    isTouch = true;   }     /**    * 设置为不可操作    */   public void disableTouch() {    isTouch = false;   }     private Timer timer = new Timer();   private TimerTask task = null;     /**    * 清除密码    */   public void clearPassword() {    clearPassword(CLEAR_TIME);   }     /**    * 清除密码    */   public void clearPassword(final long time) {    if (time > 1) {     if (task != null) {      task.cancel();      Log.d("task", "clearPassword cancel()");     }     lineAlpha = 130;     postInvalidate();     task = new TimerTask() {      public void run() {       reset();       postInvalidate();      }     };     Log.d("task", "clearPassword schedule(" + time + ")");     timer.schedule(task, time);    } else {     reset();     postInvalidate();    }     }     //   private OnCompleteListener mCompleteListener;     /**    * @param mCompleteListener    */   public void setOnCompleteListener(OnCompleteListener mCompleteListener) {    this.mCompleteListener = mCompleteListener;   }     /**    * 取得密码    *     * @return    */   private String getPassword() {    SharedPreferences settings = this.getContext().getSharedPreferences(      this.getClass().getName(), 0);    return settings.getString("password", ""); // , "0,1,2,3,4,5,6,7,8"   }     /**    * 密码是否为空    *     * @return    */   public boolean isPasswordEmpty() {    return StringUtil.isEmpty(getPassword());   }     public boolean verifyPassword(String password) {    boolean verify = false;    if (StringUtil.isNotEmpty(password)) {     // 或者是超级密码     if (password.equals(getPassword())       || password.equals("0,1,2,3,4,5,6,7,8")) {      verify = true;     }    }    return verify;   }     /**    * 设置密码    *     * @param password    */   public void resetPassWord(String password) {    SharedPreferences settings = this.getContext().getSharedPreferences(      this.getClass().getName(), 0);    Editor editor = settings.edit();    editor.putString("password", password);    System.out.println("password:" + password);    editor.commit();   }     public int getPasswordMinLength() {    return passwordMinLength;   }     public void setPasswordMinLength(int passwordMinLength) {    this.passwordMinLength = passwordMinLength;   }     /**    * 轨迹球画完成事件    *     * @author Dell    */   public interface OnCompleteListener {    /**     * 画完了     *      * @param str     */    public void onComplete(String password);   }  }

2.设置密码实现类 SetPasswordActivity
package com.huangcheng.lock;    import com.huangcheng.lock.LocusPassWordView.OnCompleteListener;  import com.huangcheng.lock.util.StringUtil;    import android.app.Activity;  import android.os.Bundle;  import android.view.View;  import android.view.View.OnClickListener;  import android.widget.TextView;  import android.widget.Toast;    public class SetPasswordActivity extends Activity  {   private LocusPassWordView lpwv;   private String password;   private boolean needverify = true;     @Override   public void onCreate(Bundle savedInstanceState)   {    super.onCreate(savedInstanceState);    setContentView(R.layout.setpassword_activity);    setTitle("密码设置");    lpwv = (LocusPassWordView) this.findViewById(R.id.mLocusPassWordView);    lpwv.setOnCompleteListener(new OnCompleteListener()    {     @Override     public void onComplete(String mPassword)     {      password = mPassword;      if (needverify)      {       if (lpwv.verifyPassword(mPassword))       {        showDialog("密码输入正确,请输入新密码!");        needverify = false;       }       else       {        showDialog("错误的密码,请重新输入!");        password = "";       }      }     }    });      OnClickListener mOnClickListener = new OnClickListener()    {     @Override     public void onClick(View v)     {      switch (v.getId())      {      case R.id.tvSave:       if (StringUtil.isNotEmpty(password))       {        lpwv.resetPassWord(password);        showDialog("密码修改成功,请记住密码.");        SetPasswordActivity.this.finish();        System.out.println(password);       }       else       {        showDialog("密码不能为空,请输入密码.");       }       break;      case R.id.tvReset:       lpwv.clearPassword();       break;      }     }    };    TextView buttonSave = (TextView) this.findViewById(R.id.tvSave);    buttonSave.setOnClickListener(mOnClickListener);    TextView tvReset = (TextView) this.findViewById(R.id.tvReset);    tvReset.setOnClickListener(mOnClickListener);    // 如果密码为空,直接输入密码    if (lpwv.isPasswordEmpty())    {     this.needverify = false;     Toast.makeText(SetPasswordActivity.this, "请输入密码", Toast.LENGTH_SHORT).show();    }   }     @Override   protected void onStart()   {    super.onStart();   }     @Override   protected void onStop()   {    super.onStop();   }     private void showDialog(String title)   {    Toast.makeText(SetPasswordActivity.this, title, Toast.LENGTH_SHORT).show();   }  }
3.登录界面 LoginActivity
package com.huangcheng.lock;    import com.huangcheng.lock.LocusPassWordView.OnCompleteListener;    import android.app.Activity;  import android.app.AlertDialog;  import android.content.DialogInterface;  import android.content.Intent;  import android.os.Bundle;  import android.view.View;  import android.view.View.OnClickListener;  import android.widget.Toast;    public class LoginActivity extends Activity {   private LocusPassWordView lpwv;   private int num = 0;     @Override   public void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.login_activity);    setTitle("系统登陆");    lpwv = (LocusPassWordView) this.findViewById(R.id.mLocusPassWordView);    lpwv.setOnCompleteListener(new OnCompleteListener() {     @Override     public void onComplete(String mPassword) {      // 如果密码正确,则进入主页面。      if (lpwv.verifyPassword(mPassword)) {       Toast.makeText(LoginActivity.this, "登陆成功!",         Toast.LENGTH_SHORT).show();       LoginActivity.this.finish();      } else {       Toast.makeText(LoginActivity.this, "密码输入错误,请重新输入",         Toast.LENGTH_SHORT).show();       lpwv.clearPassword();       num++;       if (num == 5) {        new AlertDialog.Builder(LoginActivity.this)          .setTitle("错误")          .setMessage("密码识别错误超过5次!")          .setPositiveButton("确定",            new DialogInterface.OnClickListener() {             public void onClick(               DialogInterface dialoginterface,               int i) {              // 按钮事件              LoginActivity.this.finish();             }            }).show();       }      }     }    });     }     @Override   protected void onStart() {    super.onStart();    // 如果密码为空,则进入设置密码的界面    View noSetPassword = (View) this.findViewById(R.id.tvNoSetPassword);    if (lpwv.isPasswordEmpty()) {     noSetPassword.setOnClickListener(new OnClickListener() {      @Override      public void onClick(View v) {       Intent intent = new Intent(LoginActivity.this,         SetPasswordActivity.class);       // 打开新的Activity       startActivity(intent);      }       });     noSetPassword.setVisibility(View.VISIBLE);    } else {     noSetPassword.setVisibility(View.GONE);    }   }     @Override   protected void onStop() {    super.onStop();   }  }
转自:http://blog.csdn.net/hc260164797/article/details/7745254