此效果源自于星球的星友的提问:
周末忙里偷闲把效果实现了一下,其实这个效果一般都是在Web上的验证,手机App多半还是短信验证码等方式,或者WebView加载的JS中的效果,不过要自定义View一下,这里我以我的思路来写一个自定义View,不过重在思路哈,不想写开源,很多的细节也就没注意,首先我们分析一下这个验证码的组成部分
1.背景图
2.空缺图
3.移动图
4.成功提示
5.滑块进度条
那么我们首先创建一个View叫做PictureV,先来绘制背景吧;
这里我先加载了一张图片作为mBitmap,然后创建了控件宽高大小一致的bgBitmap,让mBitmap填充在bgBitmap上,这是因为我们并不确认一张图片的大小到底是多少,所以通过createBitmap创建与View等宽高的画布,最后将bgBitmap绘制在View上,显示的结果如下:
然后,我们开始绘制空缺的图片,这里我随便找了一个小方块来进行绘制,看代码:
绘制空的方块只需要加载一张图片绘制出来就好了,这里我通过获得nullBitmap的宽度来作为小方块的高宽,因为我的实现是正方形的,其次计算了他默认出现的地方,也就是LINE_W,LINE_H,当然,你也可以动态随机,这个也是同理,运行一下:
可以看到方块了,那么我们现在还得绘制一块移动的方块并且截取空白方块的位置,代码如下:
由于移动的方块是需要截取空白处的,所以我们还是利用了createBitmap创建一个新的位图,他的高宽就是我们的空白块高宽,并且他的大小是我们之前绘制空白块的宽度,也就是CARD_SIZE,这里要注意的是我们绘制位图的时候x轴,也就是平行线需要使用一个变量来表示,等一下滑动的时候要动态修改的,来看下效果:
这个效果看起来还是不错的,我们现在需要其实可以处理滑动事件了,因为我们这个案例是支持手势滑动的,来看下Touch的代码:
这个方法中不仅处理了滑动事件,也处理了计时的任务,我们在按下的时候开始计时,当抬起的时候则关闭计时,这个时候就知道你移动一次所需要的时间,方便我们绘制结果提示,接着来看move方法吧,首先我们的拖动不能超过屏幕左右侧,所以我们左侧直接大于0,右侧的话则需要屏幕宽度减去方块大小,才赋值给moveX,然后刷新一下View就可以看到效果了,我们来看下Gif图片:
当然,MOVE处理移动,那么UP就要处理结果了,我需要知道你到底成功了没有,那么我们可以看到,在UP中,我们首先先remove掉计时器,不管你成功与否,这一次的计时算是结束了,然后我们判断你的移动块是否在空白块的位置,也就是LINE_W和LINE_H,这里我设置了一个errorValue 误差值,防止一些手残党对不准,当位置吻合,说明移动成功了,那我们通过接口通知外部调用对象,并且这里有一个变量isSucceed设置为true再刷新,是为了onDraw里的绘制成功提示:
moveTime就是我们计算的时间了,来看下drawSucceedText这个方法:
这里绘制了两部分,一个是背景一个是文字,背景直接RectF,至于他的位置,我们是放在底部,所以mHeight减去我们希望的高度即可,然后文本就比较麻烦了,因为我们要绘制居中,通过测量得出baseY,文本绘制居中这个可以参考资料或者网上一些人的讲解
这样就可以实现绘制的文本居中了,然后我们运行看下效果
到这里看起来效果还是不错的,不过我们还有一个滑动进度条要实现,本来正常来讲,直接绘制得了,直接绘制一个进度,一个滑块,根据滑动来实现拖动进度,不过这里我直接偷懒吧,使用进度条来实现,嘎嘎~~
那要怎么做呢? 首先新增一个SeekBar
然后PictureV新增一个接口,对外输出值,输出两个值,一个是最大值,一个是当前进度
而我们默认的当前值是moveX,而最大值则是宽度减去方块大小,接着需要新增一个对外调用的方法updateX
这个方法是提供给外部调用的,和我们的滑动事件是一样的,处理好moveX的赋值以及对成功与否的判断即可,来看下MainActivity中的调用:
来看下运行效果:
这里的时间其实是没有计算到的因为没有在ACTION_DOWN中开始计时,不过本来就是偷懒的,这个小细节也懒得管了,最后放上PictureV的全部代码:
最后运行一个Gif:
大体的实现思路是如此,也并没有进行封装处理,只是想告诉同学们一种实现方式,当然,要想做到图片上的那个效果,还需要进行细化,可以根据这个View自己去魔改一下即可,思路 > Demo
好了,喜欢的点个关注哦~