android自定义View实现手势解锁

android自定义View实现手势解锁 有时候为了程序的安全性,我们经常要采取一些安全措施,就像我们常用的支付宝那样,隔一定的时间再回到应用程序时会让用户利用手势去解锁应用程序,最近由于项目需求,也要求做这样一个功能,当用户切出本应用程序15分钟后回来,让用户手势解锁,整个需求的难点就在如何实现这个手势锁,开始一点头绪也没有,没有一点思路去实现这个手势解锁功能,在google了一番后看了一篇非常好的博客后,按照博主的思路的确是可以实现一个十分不错的手势锁View,也参考了下那位大神的代码,下面是我根据他的思路和代码片段实现的一个自定义手势解锁 View,先看效果图.这是自定义View的初始效果图:以下是绘制手势时的效果图:下面是实现的demo代码:packagecom.example.gesturelock;importjava.util.ArrayList;importjava.util.List;importjava.util.Timer;importjava.util.TimerTask;importandroid.content.Context;importandroid.graphics.Canvas;importandroid.graphics.Color;importandroid.graphics.Paint;importandroid.graphics.Path;importandroid.util.AttributeSet;importandroid.view.MotionEvent;importandroid.view.View;importcom.example.gesturelock.GestureLockView.OnGestureFinishListener;publicclassMyGestureLockViewextendsView{/** * 不同状态的画笔 */privatePaint paintNormal;privatePaint paintOnTouch;privatePaint paintInnerCycle;privatePaint paintLines;privatePaint paintKeyError;privateMyCycle[]cycles;privatePath linePathnewPath();privateListInteger linedCyclesnewArrayListInteger();privateOnGestureFinishListener onGestureFinishListener;privateString key;privateint eventX,eventY;privateboolean canContinuetrue;privateboolean result;privateTimer timer;/** * 不同状态下的色值 */privateintOUT_CYCLE_NORMALColor.rgb(108,119,138);// ԲɫprivateintOUT_CYCLE_ONTOUCHColor.rgb(025,066,103);// ѡԲɫprivateintINNER_CYCLE_ONTOUCHColor.rgb(002,210,255);// ѡԲɫprivateintLINE_COLORColor.argb(127,002,210,255);// ɫprivateintERROR_COLORColor.argb(127,255,000,000);publicvoidsetOnGestureFinishListener(OnGestureFinishListener onGestureFinishListener){this.onGestureFinishListeneronGestureFinishListener;}publicvoidsetKey(String key){this.keykey;}publicMyGestureLockView(Context context,AttributeSet attrs,int defStyle){super(context,attrs,defStyle);init();}publicMyGestureLockView(Context context,AttributeSet attrs){super(context,attrs);init();}publicMyGestureLockView(Context context){super(context);init();}privatevoidinit(){paintNormalnewPaint();paintNormal.setAntiAlias(true);paintNormal.setStrokeWidth(3);paintNormal.setStyle(Paint.Style.STROKE);paintOnTouchnewPaint();paintOnTouch.setAntiAlias(true);paintOnTouch.setStrokeWidth(3);paintOnTouch.setStyle(Paint.Style.STROKE);paintInnerCyclenewPaint();paintInnerCycle.setAntiAlias(true);paintInnerCycle.setStyle(Paint.Style.FILL);paintLinesnewPaint();paintLines.setAntiAlias(true);paintLines.setStyle(Paint.Style.STROKE);paintLines.setStrokeWidth(6);paintKeyErrornewPaint();paintKeyError.setAntiAlias(true);paintKeyError.setStyle(Paint.Style.STROKE);paintKeyError.setStrokeWidth(3);}OverrideprotectedvoidonMeasure(int widthMeasureSpec,int heightMeasureSpec){// TODO Auto-generated method stubsuper.onMeasure(widthMeasureSpec,heightMeasureSpec);}OverrideprotectedvoidonLayout(boolean changed,int left,int top,int right,int bottom){// TODO Auto-generated method stubsuper.onLayout(changed,left,top,right,bottom);int perSize0;if(cyclesnull(perSizegetWidth()/6)0){cyclesnewMyCycle[9];for(int i0;i3;i){for(int j0;j3;j){MyCycle cyclenewMyCycle();cycle.setNum(i*3j);cycle.setOx(perSize*(j*21));cycle.setOy(perSize*(i*21));cycle.setR(perSize*0.5f);cycles[i*3j]cycle;}}}}/** * 绘制所需要绘制的内容 */OverrideprotectedvoidonDraw(Canvas canvas){// TODO Auto-generated method stubsuper.onDraw(canvas);for(int i0;icycles.length;i){if(!canContinue!result){paintOnTouch.setColor(ERROR_COLOR);paintInnerCycle.setColor(ERROR_COLOR);paintLines.setColor(ERROR_COLOR);}elseif(cycles[i].isOnTouch()){paintOnTouch.setColor(OUT_CYCLE_ONTOUCH);paintInnerCycle.setColor(INNER_CYCLE_ONTOUCH);paintLines.setColor(LINE_COLOR);}else{paintNormal.setColor(OUT_CYCLE_NORMAL);paintInnerCycle.setColor(INNER_CYCLE_ONTOUCH);paintLines.setColor(LINE_COLOR);}if(cycles[i].isOnTouch()){canvas.drawCircle(cycles[i].getOx(),cycles[i].getOy(),cycles[i].getR(),paintOnTouch);drawInnerBuleCycle(cycles[i],canvas);}else{canvas.drawCircle(cycles[i].getOx(),cycles[i].getOy(),cycles[i].getR(),paintNormal);}}drawLine(canvas);}/** * 绘制大圆里的小圆 * * param canvas */privatevoiddrawInnerBuleCycle(MyCycle cycle,Canvas canvas){canvas.drawCircle(cycle.getOx(),cycle.getOy(),cycle.getR()/3,paintInnerCycle);}privatevoiddrawLine(Canvas canvas){linePath.reset();if(linedCycles.size()0){for(int i0;ilinedCycles.size();i){int indexlinedCycles.get(i);if(i0){// 设置为整条路径的起点linePath.moveTo(cycles[index].getOx(),cycles[i].getOy());}else{linePath.lineTo(cycles[i].getOx(),cycles[i].getOy());}}linePath.lineTo(eventX,eventY);canvas.drawPath(linePath,paintLines);}}/** * 根据手择时触摸点的不同,修改对应的状态值 */OverridepublicbooleanonTouchEvent(MotionEvent event){if(canContinue){switch(event.getAction()){caseMotionEvent.ACTION_DOWN:caseMotionEvent.ACTION_MOVE:eventX(int)event.getX();eventY(int)event.getY();for(int i0;icycles.length;i){if(cycles[i].isPointIn(eventX,eventY)){cycles[i].setOnTouch(true);if(!linedCycles.contains(cycles[i].getNum())){linedCycles.add(cycles[i].getNum());}}}break;caseMotionEvent.ACTION_UP:canContinuefalse;StringBuffer sbnewStringBuffer();for(int i0;ilinedCycles.size();i){sb.append(linedCycles.get(i));}resultkey.equals(sb.toString());if(onGestureFinishListener!null){onGestureFinishListener.OnGestureFinish(result);}timernewTimer();timer.schedule(newTimerTask(){Overridepublicvoidrun(){// 回到初始状态eventXeventY0;for(int i0;icycles.length;i){cycles[i].setOnTouch(false);}linedCycles.clear();linePath.reset();canContinuetrue;postInvalidate();}},1000);break;}}invalidate();returntrue;}}自定义圆类:packagecom.example.gesturelock;publicclassMyCycle{privateint ox;// Բĺprivateint oy;// Բprivatefloat r;// 뾶privateInteger num;// ֵprivateboolean onTouch;// falseδѡpublicintgetOx(){returnox;}publicvoidsetOx(int ox){this.oxox;}publicintgetOy(){returnoy;}publicvoidsetOy(int oy){this.oyoy;}publicfloatgetR(){returnr;}publicvoidsetR(float r){this.rr;}publicIntegergetNum(){returnnum;}publicvoidsetNum(Integer num){this.numnum;}publicbooleanisOnTouch(){returnonTouch;}publicvoidsetOnTouch(boolean onTouch){this.onTouchonTouch;}publicbooleanisPointIn(int x,int y){double distanceMath.sqrt((x-ox)*(x-ox)(y-oy)*(y-oy));returndistancer;}}思路:1.自定义一个 View和MyCircle类,将九个MyCircle类的实例绘制到View中.2.处理onTouch事件,根据不同的事件修改MyCircle实例的状态,并调用更新invaildate更新View3.重写onDraw()方法,根据不同的状态去重新绘制整个View以上就是本文的全部内容希望对大家的学习有所帮助。更多Android进阶指南 可以扫码 解锁《Android十大板块文档》1.Android车载应用开发系统学习指南附项目实战2.Android Framework学习指南助力成为系统级开发高手3.2023最新Android中高级面试题汇总解析告别零offer4.企业级Android音视频开发学习路线项目实战附源码5.Android Jetpack从入门到精通构建高质量UI界面6.Flutter技术解析与实战跨平台首要之选7.Kotlin从入门到实战全方面提升架构基础8.高级Android插件化与组件化含实战教程和源码9.Android 性能优化实战360°全方面性能调优10.Android零基础入门到精通高手进阶之路敲代码不易关注一下吧。ღ( ´ᴗ )