本文共 8236 字,大约阅读时间需要 27 分钟。
在开发中为了防止恶意破解、恶意提交等行为,所以我们在提交数据时,都会使用验证功能,去尽量区别人机。在Android应用中我们同样需要这一功能,去有效的避开恶意注册,恶意攻击。
上篇文章:中,介绍了一种,数字英文随机生成的图片验证码,使用很简单,一行代码,调用一个工具类,就能完美的实现图片验证码的显示。
另外一种常见的,可以实现简单人机区别检测的方法,滑动验证条,效果如下:
理清思路,接下来看下代码吧!
首先制作我们的拓展自定义SeekBar实现滑动条,然后根据dispatchTouchEvent
进行事件的拦截,过滤非起始点的点击事件,避免SeekBar自带的点击跳转进度的效果,不然的话还叫什么滑动进度条。
ValidationSeekBar
的Left
点坐标位为起始,根据thumb
的大概大小计算出有效触摸范围,而其余的,通过 return true;
来进行拦截。 public class ValidationSeekBar extends AppCompatSeekBar { //验证条的宽度 private int index = 0; //点击状态 private boolean k = true; private int xDOWN; class measureRunnable implements Runnable { @Override public void run() { //重新测绘获取验证条宽度 ValidationSeekBar.this.measure(0, 0); index = ValidationSeekBar.this.getLeft(); Log.e("ValidationSeekBar", "index:" + index); } } public ValidationSeekBar(Context context) { super(context); this.post(new measureRunnable()); } public ValidationSeekBar(Context context, AttributeSet attrs) { super(context, attrs); this.post(new measureRunnable()); } public ValidationSeekBar(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); this.post(new measureRunnable()); } @Override public boolean dispatchTouchEvent(MotionEvent event) { int x = (int) event.getX(); //过滤SeekBar的点击事件 if (event.getAction() == MotionEvent.ACTION_DOWN) { xDOWN = (int) event.getX(); k = true; if (xDOWN - index > 200) { k = false; return true; } } //过滤SeekBar的点击事件 if (event.getAction() == MotionEvent.ACTION_UP) { k = true; if (xDOWN - index > 200) { k = false; return true; } } if (event.getAction() == MotionEvent.ACTION_MOVE) { if (!k) { return true; } } return super.dispatchTouchEvent(event); }}
以上,我的ValidationSeekBar就完成了。接下来去搭建我们的xml布局吧。以下是滑动条的布局:使用我们的ValidationSeekBar以及TextView组合出相关的提示效果。
来看一下整体的布局文件:
这样整个界面的布局就出来了,但是还不够,我们还希望为我们的ValidationSeekBar增加更多的状态反馈效果。那么我们需要制作一些progressDrawable
和thumb
到这里,我们的界面以及材料都已经准备好了,接下里我们去Activity
中看一下操作流程吧
public class MainActivity extends AppCompatActivity implements SeekBar.OnSeekBarChangeListener { private TextView tv; private ValidationSeekBar seekBar; Handler handler = new Handler(); private Button getCode; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); getCode = (Button) findViewById(R.id.getCode); tv = (TextView) findViewById(R.id.tv); seekBar = (ValidationSeekBar) findViewById(R.id.sb); seekBar.setOnSeekBarChangeListener(this); } /** * seekBar进度变化时回调 * * @param seekBar * @param progress * @param fromUser */ @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { if (seekBar.getProgress() == seekBar.getMax()) { } else { tv.setVisibility(View.INVISIBLE); } } /** * seekBar开始触摸时回调 * * @param seekBar */ @Override public void onStartTrackingTouch(SeekBar seekBar) { } /** * seekBar停止触摸时回调 * * @param seekBar */ @Override public void onStopTrackingTouch(final SeekBar seekBar) { //验证错误时的滑动条样式 if (seekBar.getProgress() != seekBar.getMax()) { seekBar.setProgressDrawable(getResources().getDrawable(R.drawable.seekbar_error_bg)); seekBar.setThumb(getResources().getDrawable(R.drawable.er)); seekBar.setThumbOffset(0); int progress = seekBar.getProgress(); seekBar.setProgress(0); seekBar.setProgress(progress); //错误状态延时警示 handler.postDelayed(new Runnable() { @Override public void run() { //错误回退动画效果 runFloat(seekBar.getProgress()); } }, 400); } //设置验证成功的滑动条样式 if (seekBar.getProgress() == seekBar.getMax()) { seekBar.setThumb(getResources().getDrawable(R.drawable.gd)); seekBar.setProgressDrawable(getResources().getDrawable(R.drawable.seekbar_good_bg)); seekBar.setProgress(0); seekBar.setThumbOffset(-3); seekBar.setProgress(100); //成功时的提示信息 tv.setVisibility(View.VISIBLE); tv.setTextColor(Color.rgb(0x29, 0x94, 0x6b)); tv.setText("完成验证"); //按钮状态 getCode.setBackgroundColor(getResources().getColor(android.R.color.holo_red_light)); } } private void runFloat(int Progress) { //使用ValueAnimator进行进度的偏移。 ValueAnimator valueAnimator = ValueAnimator.ofInt(Progress, 0); //动画时间,可根据需要调整 valueAnimator.setDuration(200); //动画更新监听 valueAnimator .addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator valueAnimator) { //设置进度 seekBar.setProgress(Integer.parseInt(valueAnimator .getAnimatedValue().toString())); } }); //动画状态监听 valueAnimator.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animator) { } @Override public void onAnimationEnd(Animator animator) { //重置默认的滑动条样式 seekBar.setThumb(getResources().getDrawable(R.drawable.thumb)); seekBar.setThumbOffset(-1); seekBar.setProgressDrawable(getResources().getDrawable(R.drawable.seekbar_bg)); //重置提示信息 tv.setVisibility(View.VISIBLE); tv.setTextColor(Color.GRAY); tv.setText("请按住滑块,拖动到最右边"); } @Override public void onAnimationCancel(Animator animator) { } @Override public void onAnimationRepeat(Animator animator) { } }); //开启valueAnimator valueAnimator.start(); }}
至此,我们的整个滑动验证码的制作流程就结束了,以上代码基本实现文章开头效果图以及常规的滑动验证码的需求逻辑,整体代码逻辑还是比较清晰了然的,使用起来也很方便。
**当然一定还有更多方法和更优化的逻辑,还请大家提出,共同完善,
有了需求才有了功能,有了想法才有了创作,你的反馈会是使我进步的最大动力。**觉得还不够方便?还想要什么功能?告诉我!欢迎反馈,欢迎Star。
转载地址:http://ljcfm.baihongyu.com/