android 手势解锁的实现
2016-03-09 14:40
429 查看
基本思路,继承一个view,重写其ondraw方法,在其中9个圆(也可以自己自定义属性,让使用者控制圆的个数,但是过多或者过少都会影响美观而且太复杂的话用户不容易记住自己设置的手势,所以基本可以不用考虑自定义这个属性),每个圆都有一个相当于下标的属性,用于唯一确定一个圆,最后手势的比较也是通过这个坐标点,也就是说你画的手势它只记录了下标值(比如你的手势是一个z,它记录下来的是下标的位置顺序(0124678),你同样画一个z,当时是逆向画(8764210)就没有用,因为最后比较的是下标的顺序),千万不要以为它比较的是图形,画好圆之后就可以重写view的ontouchEvent事件,根据点击的坐标记录被点击的圆,在ondraw中根据是否被点击变换图形颜色,同时画出path,以上就是基本的实现原理,接下来看看代码:
在onlayout中能获得屏幕的高和宽,所以在这里设置圆的大小等属性,接下来重写ontouchevent事件
根据我们触摸点的位置判断是不是点击了圆的位置,是的话就把这个圆的下标添加到list中,在ondraw中用于画线(就是我们的手势轨迹),抬起之后就结束本次手势,并且在绘制了手势1秒后恢复我们的view,在此期间不在响应我们的点击,否则会乱
最后是ondraw方法,在其中根据在ontouchevent中得到的list绘制手势轨迹,改变点击的圆的颜色等
参考:http://blog.csdn.net/centralperk/article/details/23374683
我整理之后的代码,主要简化了一些代码:http://download.csdn.net/detail/u012806692/9456989
@Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); int perSize = 0; if (cycles == null && (perSize = getWidth() / 6) > 0) { cycles = new MyCircle[9]; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { MyCircle cycle = new MyCircle(); cycle.setNum(i * 3 + j); cycle.setOx(perSize * (j * 2 + 1)); cycle.setOy(perSize * (i * 2 + 1)); cycle.setR(perSize * 0.5f); cycles[i * 3 + j] = cycle; } } } }
在onlayout中能获得屏幕的高和宽,所以在这里设置圆的大小等属性,接下来重写ontouchevent事件
@Override public boolean onTouchEvent(MotionEvent event) { if (canContinue) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: onGestureFinishListener.OnGestureStart(); case MotionEvent.ACTION_MOVE: canContinue = true; /** * event.getX()是相对于view的坐标点,getrawx是相对于屏幕的 */ eventX = (int) event.getX(); eventY = (int) event.getY(); for (int i = 0; i < cycles.length; i++) { if (cycles[i].isPointIn(eventX, eventY)) { cycles[i].setOnTouch(true); if (!linedCycles.contains(cycles[i].getNum())) { linedCycles.add(cycles[i].getNum()); } } } break; case MotionEvent.ACTION_UP: canContinue = false; StringBuffer sb = new StringBuffer(); for (int i = 0; i < linedCycles.size(); i++) { sb.append(linedCycles.get(i)); } if (onGestureFinishListener != null) { result = onGestureFinishListener.OnGestureFinish(sb .toString()); } timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { // 还原 eventX = eventY = 0; for (int i = 0; i < cycles.length; i++) { cycles[i].setOnTouch(false); } linedCycles.clear(); linePath.reset(); canContinue = true; postInvalidate(); timer.cancel(); } }, 1000); break; default: break; } invalidate(); } return true; }
根据我们触摸点的位置判断是不是点击了圆的位置,是的话就把这个圆的下标添加到list中,在ondraw中用于画线(就是我们的手势轨迹),抬起之后就结束本次手势,并且在绘制了手势1秒后恢复我们的view,在此期间不在响应我们的点击,否则会乱
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); for (int i = 0; i < cycles.length; i++) { if(!result){ /** * 手指已经抬起,并且手势错误 */ paintOutCycle.setColor(ERROR_COLOR); paintInnerCycle.setColor(INNER_CYCLE_ERROR_COLOR); paintLines.setColor(ERROR_COLOR); } if (cycles[i].isOnTouch()) { /** * 圆圈被选中 */ paintOutCycle.setColor(OUT_CYCLE_ONTOUCH); paintInnerCycle.setColor(INNER_CYCLE_TOUCHED); paintLines.setColor(LINE_COLOR); } else { paintOutCycle.setColor(OUT_CYCLE_NORMAL); paintInnerCycle.setColor(INNER_CYCLE_NOTOUCH); paintLines.setColor(LINE_COLOR); } canvas.drawCircle(cycles[i].getOx(), cycles[i].getOy(), cycles[i].getR(), paintOutCycle); canvas.drawCircle(cycles[i].getOx(), cycles[i].getOy(), cycles[i].getR() / 1.5f, paintInnerCycle); } drawLine(canvas); } private void drawLine(Canvas canvas) { linePath.reset(); if (linedCycles.size() > 0) { for (int i = 0; i < linedCycles.size(); i++) { int index = linedCycles.get(i); float x = cycles[index].getOx(); float y = cycles[index].getOy(); if (i == 0) { linePath.moveTo(x,y); } else { linePath.lineTo(x,y); } } if(canContinue){ linePath.lineTo(eventX,eventY); }else{ linePath.lineTo(cycles[linedCycles.get(linedCycles.size()-1)].getOx(), cycles[linedCycles.get(linedCycles.size()-1)].getOy()); } canvas.drawPath(linePath, paintLines); } }
最后是ondraw方法,在其中根据在ontouchevent中得到的list绘制手势轨迹,改变点击的圆的颜色等
参考:http://blog.csdn.net/centralperk/article/details/23374683
我整理之后的代码,主要简化了一些代码:http://download.csdn.net/detail/u012806692/9456989
相关文章推荐
- Android Studio使用Gradle进行多渠道打包
- 【android】垃圾回收机制
- android assets 下文件中文乱码解决
- Mac安装Genymotion
- Android不透明度16进制值
- 【Android 基础】Animation 动画介绍和实现
- Android Studio selector 报 Element selector must be declared 的问题
- Android Volley完全解析(一),初识Volley的基本用法
- android取图片视频的缩略图
- Android 编程下 AnimationDrawable (动画)的实现
- Android 4.4 沉浸式透明状态栏与导航栏
- android开发常见编程错误总结
- android柱状progressbar
- android 仿美团、大众点评滑动viewpager菜单栏
- Android实现分享文本和图片小功能
- Android从xml加载到View对象过程解析
- android解析xml一直报错org.xmlpull.v1.XmlPullParserException
- 【Android】如何使用安卓的logcat『整理』
- Android加载Gif和ImageView的通用解决方案:android-gif-drawable:GifTextView(2)
- 第5章 静态分析Android程序