自定义了一个简单的手势解锁View,如下图所示。
仅仅供参考。
代码:
public class Circle {
private int x;//x坐标
private int y;//y坐标
private int r;//半径
private int num;
private boolean isTouch;
public Circle(int x, int y, int r, int num) {
this.x = x;
this.y = y;
this.r = r;
this.num = num;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getR() {
return r;
}
public void setR(int r) {
this.r = r;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public boolean isTouch() {
return isTouch;
}
public void setIsTouch(boolean isTouch) {
this.isTouch = isTouch;
}
}
public class GestureLockView extends View {
Circle[] mCircles = new Circle[9];
/**
* 用来记录手指划过的结果 eg:"0124678"
*/
private StringBuilder lineNumStr = new StringBuilder();
int CIRCLE_R;// 圆环半径
int SMALL_CIR_R = 12;//被选中圆环内部圆环半径
static final int PADDING = 8;//边距
static final int VIBRAT_TIME = 200;//震动时长
static final int CHECK_TIME = 5000;//ACTION_UP后延时
int mWidth;//View 宽
int mHeight;//View 高
Paint mCirclePaint;// 圆环画笔
Paint mPathPaint;//线画笔
Paint mSelectCirPaint;//内实心圆画笔
Path mPath;//圆环 连线Path
private int lineColor = Color.GREEN;
private int circleColor = Color.GRAY;
private int circleSelectColor = Color.GREEN;
private Vibrator mVibrator;
Handler mHandler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
if (mListener != null) {
mListener.gestureResult(lineNumStr.toString());
lineNumStr.delete(0, lineNumStr.length());
}
return true;
}
});
public GestureLockView(Context context) {
this(context, null);
}
public GestureLockView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
mCirclePaint = new Paint();
mCirclePaint.setAntiAlias(true);
mCirclePaint.setStrokeWidth(4f);
mCirclePaint.setStyle(Paint.Style.STROKE);
mPathPaint = new Paint();
mPathPaint.setAntiAlias(true);
mPathPaint.setStrokeWidth(4f);
mPathPaint.setStyle(Paint.Style.STROKE);
mPathPaint.setColor(lineColor);
mSelectCirPaint = new Paint();
mSelectCirPaint.setAntiAlias(true);
mSelectCirPaint.setStyle(Paint.Style.FILL);
mSelectCirPaint.setColor(circleSelectColor);
mPath = new Path();
lineNumStr.append("");
mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawPath(mPath, mPathPaint);
for (int i = 0; i < mCircles.length; i++) {
Circle circle = mCircles[i];
if (circle.isTouch()) {
mCirclePaint.setColor(circleSelectColor);
canvas.drawCircle(circle.getX(), circle.getY(), circle.getR(), mCirclePaint);
canvas.drawCircle(circle.getX(), circle.getY(), SMALL_CIR_R, mSelectCirPaint);
} else {
mCirclePaint.setColor(circleColor);
canvas.drawCircle(circle.getX(), circle.getY(), circle.getR(), mCirclePaint);
}
}
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mWidth = w;
mHeight = h;
CIRCLE_R = mWidth / 12;
int firstX = CIRCLE_R + PADDING;
int secondX = mWidth / 2;
int thirdX = mWidth - CIRCLE_R - PADDING;
int firstY = CIRCLE_R + PADDING;
int secondY = mHeight / 2;
int thirdY = mHeight - CIRCLE_R - PADDING;
//初始化 9个圆环
mCircles[0] = new Circle(firstX, firstY, CIRCLE_R, 0);
mCircles[1] = new Circle(secondX, firstY, CIRCLE_R, 1);
mCircles[2] = new Circle(thirdX, firstY, CIRCLE_R, 2);
mCircles[3] = new Circle(firstX, secondY, CIRCLE_R, 3);
mCircles[4] = new Circle(secondX, secondY, CIRCLE_R, 4);
mCircles[5] = new Circle(thirdX, secondY, CIRCLE_R, 5);
mCircles[6] = new Circle(firstX, thirdY, CIRCLE_R, 6);
mCircles[7] = new Circle(secondX, thirdY, CIRCLE_R, 7);
mCircles[8] = new Circle(thirdX, thirdY, CIRCLE_R, 8);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float touchX = event.getX();
float touchY = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
checkPoint(touchX, touchY);
break;
case MotionEvent.ACTION_MOVE:
checkPoint(touchX, touchY);
break;
case MotionEvent.ACTION_UP:
new Timer().schedule(new TimerTask() {
@Override
public void run() {
mPath.reset();
for (Circle mCircle : mCircles) {
mCircle.setIsTouch(false);
}
postInvalidate();
mHandler.sendEmptyMessage(0x11);
}
}, CHECK_TIME);
break;
}
invalidate();
return true;
}
/**
* 检查手指划过的点是否位于 未被选中的圆环中
* 如果在则更改圆环touch属性、更新Path、更新选中结果
*
* @param touchX
* @param touchY
*/
private void checkPoint(float touchX, float touchY) {
for (Circle circle : mCircles) {
if (!circle.isTouch()) {
if (Math.abs(touchX - circle.getX()) <= circle.getR()
&& Math.abs(touchY - circle.getY()) <= circle.getR()) {
//说明选中的点在该Circle中
circle.setIsTouch(true);
mVibrator.vibrate(VIBRAT_TIME);
String line = lineNumStr.toString();
if (line.length() > 0) {
char c = line.charAt(line.length() - 1);
int index = Integer.parseInt(c + "");
mPath.quadTo(mCircles[index].getX(), mCircles[index].getY(),
circle.getX(), circle.getY());
} else {
mPath.moveTo(circle.getX(), circle.getY());
}
lineNumStr.append(circle.getNum());
}
}
}
}
private LockListener mListener;
public interface LockListener {
void gestureResult(String result);
}
public void setListener(LockListener listener) {
mListener = listener;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}