Android实现滑块拼图验证码功能

滑块拼图验证码应该算是很常见的功能了,验证码是可以区分用户是人还是机器。可以防止破解密码、刷票等恶意行为。本文将介绍Android拼图滑块验证码控件的实现过程。希望能帮助到大家。

先看最终的效果图:

本文只是做了个Demo,并没有加入到实际的项目中,所以各位童鞋可以根据自己的需求就行修改即可。

一、实现步骤:

1、定义自定义属性; 2、确认目标位置,这里使用的是阴影图片来遮盖背景图片; 3、创建与目标位置相结合的滑块图片; 4、设置目标阴影图片和滑块图片可以随机旋转,并保持一致; 5、创建拖拽条,使滑块随着拖拽条的拖拽而移动; 6、判断是否验证成功。

二、实现流程:

1、定义自定义属性 创建一个attr文件来定义一些自定义属性

   <declare-styleable name="ImageAuthenticationView">
    <!--滑块的高度-->
    <attr name="unitHeight" format="dimension" />
    <!--滑块的宽度-->
    <attr name="unitWidth" format="dimension" />
    <!--滑块占图片高度的比例-->
    <attr name="unitHeightScale" format="integer" />
    <!--滑块占图片宽度的比例-->
    <attr name="unitWidthScale" format="integer" />
    <!--滑块边框的图片资源-->
    <attr name="unitShadeSrc" format="reference" />
    <!--阴影部分的图片资源-->
    <attr name="unitShowSrc" format="reference" />
    <!--是否需要旋转-->
    <attr name="needRotate" format="boolean" />
    <!--验证时的误差值-->
    <attr name="deviate" format="integer" />
  </declare-styleable>

2、确认目标位置,这里使用的是阴影图片来遮盖背景图片

 /**
   * 创建目标图片(阴影部分)
   */
  private Bitmap drawTargetBitmap() {
    // 绘制图片
    Bitmap showB;
    if (null != mShowBp) {
      showB = handleBitmap(mShowBp, mUintWidth, mUintHeight);
    } else {
      showB = handleBitmap(BitmapFactory.decodeResource(getResources(), R.mipmap.puzzle_show), mUintWidth, mUintHeight);
    }
    // 如果需要旋转图片,进行旋转,旋转后为了保持和滑块大小一致,需要重新缩放比例
    if (needRotate) {
      showB = handleBitmap(rotateBitmap(rotate, showB), mUintWidth, mUintHeight);
    }
    return showB;
  }

3、创建与目标位置相结合的滑块图片

 /**
   * 创建结滑块图片
   *
   * @param bp
   */
  private Bitmap drawResultBitmap(Bitmap bp) {
    // 绘制图片
    Bitmap shadeB;
    if (null != mShadeBp) {
      shadeB = handleBitmap(mShadeBp, mUintWidth, mUintHeight);
    } else {
      shadeB = handleBitmap(BitmapFactory.decodeResource(getResources(), R.mipmap.puzzle_shade), mUintWidth, mUintHeight);
    }
    // 如果需要旋转图片,进行旋转,旋转后为了和画布大小保持一致,避免出现图像显示不全,需要重新缩放比例
    if (needRotate) {
      shadeB = handleBitmap(rotateBitmap(rotate, shadeB), mUintWidth, mUintHeight);
    }
    Bitmap resultBmp = Bitmap.createBitmap(mUintWidth, mUintHeight,
        Bitmap.Config.ARGB_8888);
    Paint paint = new Paint();
    paint.setAntiAlias(true);
    Canvas canvas = new Canvas(resultBmp);
    canvas.drawBitmap(shadeB, new Rect(0, 0, mUintWidth, mUintHeight),
        new Rect(0, 0, mUintWidth, mUintHeight), paint);
    // 选择交集去上层图片
    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY));
    canvas.drawBitmap(bp, new Rect(0, 0, mUintWidth, mUintHeight),
        new Rect(0, 0, mUintWidth, mUintHeight), paint);
    return resultBmp;
  }

4、设置目标阴影图片和滑块图片可以随机旋转,并保持一致

 /**
   * 旋转图片
   *
   * @param degree
   * @param bitmap
   * @return
   */
  public Bitmap rotateBitmap(int degree, Bitmap bitmap) {
    Matrix matrix = new Matrix();
    matrix.postRotate(degree);
    Bitmap bm = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
        bitmap.getHeight(), matrix, true);
    return bm;
  }

5、创建拖拽条,使滑块随着拖拽条的拖拽而移动

  //滑块监听
    mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
      @Override
      public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
        //设置滑块移动距离
        mDY.setUnitMoveDistance(mDY.getAverageDistance(seekBar.getMax()) * i);
      }

      @Override
      public void onStartTrackingTouch(SeekBar seekBar) {

      }

      @Override
      public void onStopTrackingTouch(SeekBar seekBar) {
        //验证是否拼接成功
        mDY.testPuzzle();
      }
    });

6、判断是否验证成功

/**
   * 验证是否拼接成功
   */
  public void testPuzzle() {
    if (Math.abs(mUnitMoveDistance - mUnitRandomX) <= DEFAULT_DEVIATE) {
      if (null != mlistener) {
        mlistener.onSuccess();
      }
    } else {
      if (null != mlistener) {
        mlistener.onFail();
      }
    }
  }

三、完整代码

1、自定义控件内容太多这里就不放出来了,完整Demo源码会放在文章后面;

2、代码逻辑

public class MainActivity extends Activity {

  //滑块
  private SeekBar mSeekBar;
  //自定义的控件
  private ImageAuthenticationView mDY;
  private Button btn;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    initView();
    initListener();
  }

  private void initView() {
    mDY = findViewById(R.id.dy_v);
    mSeekBar = findViewById(R.id.sb_dy);
    btn = findViewById(R.id.btn);
  }

  private void initListener() {
    //滑块监听
    mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
      @Override
      public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
        //设置滑块移动距离
        mDY.setUnitMoveDistance(mDY.getAverageDistance(seekBar.getMax()) * i);
      }

      @Override
      public void onStartTrackingTouch(SeekBar seekBar) {

      }

      @Override
      public void onStopTrackingTouch(SeekBar seekBar) {
        //验证是否拼接成功
        mDY.testPuzzle();
      }
    });

    //控件监听
    mDY.setPuzzleListener(new ImageAuthenticationView.onPuzzleListener() {
      @Override
      public void onSuccess() {
        //mSeekBar.setEnabled(false);//禁止滑动
        Toast.makeText(MainActivity.this, "验证成功", Toast.LENGTH_SHORT).show();
      }

      @Override
      public void onFail() {
        Toast.makeText(MainActivity.this, "验证失败", Toast.LENGTH_SHORT).show();
        mSeekBar.setProgress(0);
      }
    });

    //重置
    btn.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
        //mSeekBar.setEnabled(true);
        mSeekBar.setProgress(0);
        mDY.reSet();
      }
    });
  }
}

3、布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:dy="http://schemas.android.com/apk/res-auto"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:gravity="center"
  android:orientation="vertical"
  android:paddingLeft="10dp"
  android:paddingTop="10dp"
  android:paddingRight="10dp"
  android:paddingBottom="10dp"
  tools:context=".MainActivity">

  <com.sjl.keeplive.slideImg.ImageAuthenticationView
    android:id="@+id/dy_v"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:scaleType="centerCrop"
    android:layout_marginBottom="10dp"
    android:src="@mipmap/test"
    dy:needRotate="true"
    dy:unitHeight="60dp"
    dy:unitShadeSrc="@mipmap/puzzle_shade"
    dy:unitShowSrc="@mipmap/puzzle_show"
    dy:unitWidth="80dp" />

  <SeekBar
    android:id="@+id/sb_dy"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@drawable/bg_seekbar"
    android:max="100" />

  <Button
    android:id="@+id/btn"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="重置"/>
</LinearLayout>

源码下载

到此这篇关于Android实现滑块拼图验证码功能的文章就介绍到这了,更多相关Android 滑块拼图验证码内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

时间: 2021-02-23

Android开发中通过手机号+短信验证码登录的实例代码

首先,需要一个电话号码,目前很多账户都是将账户名设置成手机号,然后点击按钮获取手机验证码. 其次,你需要后台给你手机短信的验证接口,各个公司用的不一样,这个身为前端,不需要你来考虑,你只要让你后台给你写好接口,你直接调用就好了. activity_login.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.andr

Android实现短信验证码获取自动填写功能(详细版)

现在的应用在注册登录或者修改密码中都用到了短信验证码,那在android中是如何实现获取短信验证码并自动填写的呢? 首先,需要要在manifest中注册接收和读取短信的权限: <uses-permission android:name="android.permission.RECEIVE_SMS"></uses-permission> <uses-permission android:name="android.permission.READ_

Android获取短信验证码的实现方法

先给大家展示下效果图,如果感觉不错,请参考实现思路详解 Android开发中关于短息验证码的设计层出不穷,越来越多的应用为了更好的提高软件的安全性,开始使用通过服务器向用户发送验证码的方式,来保护用户个人信息的安全性.无论是用户注册时的信息验证还是当用户发出找回密码请求时的短信验证,他们的工作原理大致上是一致的,因为项目的需要研究了一下关于这方面的知识,本篇我将带领大家一起实现这一当下流行的设计方案. 众所周知,短信验证需要服务器端生成一个验证码,然后发送到用户输入的手机上,这个过程需要服务器主

Android实现短信验证码自动填写功能

本实例为大家分享了Android实现短信验证码自动填写功能,供大家参考,具体内容如下 实现思路很简单: 1.在需要输入验证码的Activity代码注册监听短信的广播 2.拦截短信,获取其中的验证码 3.回写到EditText private SmsReciver smsReciver = new SmsReciver(); /** 收到短信Action **/ String ACTION_SMS_RECIVER = "android.provider.Telephony.SMS_RECEIVED

Android开发工程中集成mob短信验证码功能的方法

一.前言 现在的app基本上都需要用到短信功能,注册时或者有消息通知时需要给用户发送一条短信,但是对于个人开发者来说,去买第三方的短信服务实在是有点奢侈,很好的是mob为我们提供了免费的短信验证码服务功能,我不是打广告,的确觉得这项服务很不错.那么下面就简单讲一下如何在自己的工程里集成mob的短信功能,其实整个流程并不复杂,只是个人觉得mob的官方文档有点小乱,官方Demo也有点小复杂,同时有一些细节地方容易被忽视,也会导致一些问题. PS:太喜欢mob的logo了. 二.实现过程 本篇只涉及A

Android实现短信验证码自动拦截读取功能

知识准备:  1.观察者模式的理解[文章稍后来到~~]  2.Android的Cursor使用[Android基础]  3.正则表达式使用[Java基础]  4.Handler使用[Android基础] 代码整理: MainActivity.java import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.suppo

Android实现获取短信验证码并自动填写功能

本文实例为大家分享了Android短信验证码获取并自动填写功能的具体代码,供大家参考,具体内容如下 代码如下: MainActivity public class MainActivity extends AppCompatActivity { public static TextView mText; private SmsContent content; @Override protected void onCreate(Bundle savedInstanceState) { super.

android实现图片验证码方法解析(自绘控件)

自绘控件的内容都是自己绘制出来的 大致流程如下: 1.定义一个类继承view 1.使用TypedArray初始化属性集合     在view的构造方法中 有一个AttributeSet的参数 很明显是用来保存控件属性信息的 我们也的确可以通过循环然后用键值对的方式获取信息 而TypedArray是用来简化我们的工作的 2.重写onMeasure 测量控件大小 3.重写onDraw 绘制控件 2.根据需求在attrs文件中自定义属性 declare-styleable 声明自定义属性可以自定义一个

Android栗子の图片验证码生成实例代码

废话不多说了,下面一段代码给大家分享android 生成栗子图片验证码功能,具体代码如下所示: import java.util.Random; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; public class

Android UI开发 View自绘控件 分享

很多时候想要设计漂亮的Android UI,使用Android自带的控件无法满足我们的需要就要考虑自绘控件,在Android界面显示类View,可以通过继承扩展重写相关方法来实现我们的图形绘制. 首先我们需要了解下View类的底层实现,在SDK中我们可以看到View直接继承于Java的基类Object,实现了图形绘制和按键事件 Drawable.Callback KeyEvent.Callback的相关方法,我们自绘时主要实现其内部的onDraw方法,相关的界面计算可以重写onMeasure方法

Android 自绘控件

由于公司项目的需求,需要绘制一条竖直的间断线作为分割线.这个可坑了爹了,以前只搞过水平的间断线,只要通过shape也可以简单的画出来,但是千万记得把hardwareAccelerated给关了,不然水平的虚线还是会是实线,这个以前也是我趟过的一个坑.那咋办呢,找不到原生的解决方案,不就是一条简单的间断线嘛,还能难住我等程序猿?这个时候,首先联想到的就是自绘控件了. 自绘控件,顾名思义就是控件所展示的内容都是我们自己绘制上去的.所有的绘制操作就是在onDraw()方法里面进行的,当然我们的这个自定

Android编程获取屏幕宽高与获取控件宽高的方法

本文实例讲述了Android编程获取屏幕宽高与获取控件宽高的方法.分享给大家供大家参考,具体如下: 获取屏幕宽高 // 获取屏幕宽高(方法1) int screenWidth = getWindowManager().getDefaultDisplay().getWidth(); // 屏幕宽(像素,如:480px) int screenHeight = getWindowManager().getDefaultDisplay().getHeight(); // 屏幕高(像素,如:800p) L

Android仿英语流利说取词放大控件的实现方法(附demo源码下载)

本文实例讲述了Android仿英语流利说取词放大控件的实现方法.分享给大家供大家参考,具体如下: 1 取词放大控件 英语流利说是一款非常帮的口语学习app,在app的修炼页面长按屏幕,会弹出一个放大镜,当手指移到某个单词的附近,可以看到该英文单词会被选中,效果如下图所示: 2 代码示例 该控件挺有意思,于是我写了个简单的demo,完整实例代码点击此处本站下载.,程序运行后的效果如下: 3 实现原理 该控件的实现原理比较简单,下面介绍几个比较重要的类 ① WordView 在实习该控件的过程中,我

Android自定义控件之创建可复用的组合控件

前面已学习了一种自定义控件的实现,是Andriod 自定义控件之音频条,还没学习的同学可以学习下,学习了的同学也要去温习下,一定要自己完全的掌握了,再继续学习,贪多嚼不烂可不是好的学习方法,我们争取学习了一种技术就会一种技术,而且不光看了就算了,最好的方法就是看完我自己再练习下,再扩展下,在原来的基础上在添加一些东西,比如,增加一些功能实现等等. 今天我们打算学习下另外一种自定义控件,就是创建可重复使用的组合控件,那么问题来了: 什么是可重复使用? 就是在应用中,可以在多个地方共同使用一套代码.

Android开发之无痕过渡下拉刷新控件的实现思路详解

相信大家已经对下拉刷新熟悉得不能再熟悉了,市面上的下拉刷新琳琅满目,然而有很多在我看来略有缺陷,接下来我将说明一下存在的缺陷问题,然后提供一种思路来解决这一缺陷,废话不多说!往下看嘞! 1.市面一些下拉刷新控件普遍缺陷演示 以直播吧APP为例: 第1种情况: 滑动控件在初始的0位置时,手势往下滑动然后再往上滑动,可以看到滑动到初始位置时滑动控件不能滑动. 原因: 下拉刷新控件响应了触摸事件,后续的一系列事件都由它来处理,当滑动控件到顶端的时候,滑动事件都被下拉刷新控件消费掉了,传递不到它的子控件

Android下拉刷新上拉加载控件(适用于所有View)

前面写过一篇关于下拉刷新控件的文章下拉刷新控件终结者:PullToRefreshLayout,后来看到好多人还有上拉加载更多的需求,于是就在前面下拉刷新控件的基础上进行了改进,加了上拉加载的功能.不仅如此,我已经把它改成了对所有View都通用!可以随心所欲使用这两个功能~~ 我做了一个大集合的demo,实现了ListView.GridView.ExpandableListView.ScrollView.WebView.ImageView.TextView的下拉刷新和上拉加载.后面会提供demo的

Android编程实现点击EditText之外的控件隐藏软键盘功能

本文实例讲述了Android编程实现点击EditText之外的控件隐藏软键盘功能.分享给大家供大家参考,具体如下: 工具类 ... public static void hideKeyboard(Context ctx) { if (ctx != null) { View view = ((Activity) ctx).getCurrentFocus(); if (view != null) { InputMethodManager inputManager = (InputMethodMana