Android实现支付宝AR扫描动画效果

支付宝AR扫描效果动画实现,具体内容如下

之前一个网友说想要一个支付宝扫描动画的效果demo,所以又花了点时间做了下这个东西,先看效果图

说一下实现的思路,如图中最外围的蓝色的是用两个相距180°的圆弧实现的,再往里又是两个红色的圆弧再往里面是一个红色的圆,最里面的白色的是由4个间隔的白色圆弧组成的,其实说明白的就是简单的图形的堆积.然后通过控制绘制圆弧的起始角度进行旋转的动画.扫描的红色线条是一张渐变的图片,通过平移动画实现扫描的效果.

这个自定义View 的代码如下:

package cn.com.hadon.scanner;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;

/**
 * Created by Mr.Wang on 2017/5/8.
 */

public class ScanView extends View {
 private Paint blueCirclePaint;//蓝色圈的画笔
 private Paint redCirclePaint;//红色圈的画笔
 private Paint whiteCirclePaint;//白色圈的画笔

 public static final int STATE_READY = 1;
 public static final int STATE_SCANING = 2;
 public static final int STATE_SUCCESS = 3;

 //定义圆弧的宽度
 private static final int BLUE_CIRCLE_BORDER_WIDTH = 8;
 private static final int INSIDER_RED_CIRCLE_BORDER_WIDTH = 20;
 private static final int OUTSIDER_CIRCLE_BORDER_WIDTH = 20;
 private static final int WHITE_CIRCLE_BORDER_WIDTH = 20;

 private int minLength;//中心最大圆的直径
 private int radius;//中心最大圆的半径
 private int centerX;//中心点X坐标
 private int centerY;//中心点Y坐标

 private Bitmap scanerbitmap;//条形扫描图片
 private int curState = STATE_SCANING;//初始状态

 public ScanView(Context context, @Nullable AttributeSet attrs) {
  super(context, attrs);
  //初始化一些变量
  scanerbitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.scaner);
  blueCirclePaint = new Paint();
  redCirclePaint = new Paint();
  whiteCirclePaint = new Paint();

  blueCirclePaint.setColor(Color.BLUE);
  blueCirclePaint.setAntiAlias(true);
  blueCirclePaint.setStyle(Paint.Style.STROKE);
  blueCirclePaint.setStrokeWidth(BLUE_CIRCLE_BORDER_WIDTH);

  redCirclePaint.setColor(Color.RED);
  redCirclePaint.setAntiAlias(true);
  redCirclePaint.setStyle(Paint.Style.STROKE);
  redCirclePaint.setStrokeWidth(INSIDER_RED_CIRCLE_BORDER_WIDTH);

  whiteCirclePaint.setColor(Color.WHITE);
  whiteCirclePaint.setAntiAlias(true);
  whiteCirclePaint.setStyle(Paint.Style.STROKE);
  whiteCirclePaint.setStrokeWidth(WHITE_CIRCLE_BORDER_WIDTH);

 }

 @Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  super.onMeasure(widthMeasureSpec, heightMeasureSpec);
  int width = MeasureSpec.getSize(widthMeasureSpec);
  int height = MeasureSpec.getSize(heightMeasureSpec);
  centerX = width / 2;
  centerY = height / 2;
  //获取直径和半径以及中心带你坐标方便后面的计算
  minLength = Math.min(width, height);
  radius = minLength / 2;

 }

 /**
  * 公开方法设置当前的状态值
  * @param state
  */
 public void setState(int state) {
  this.curState = state;
 }

 @Override
 protected void onDraw(Canvas canvas) {
  super.onDraw(canvas);
  canvas.drawColor(Color.TRANSPARENT);
  switch (curState) {
   case STATE_READY:
    drawWhiteCircle(canvas);
    drawInsiderRedCircle(canvas);
    drawOutsiderRedCircle(canvas);
    break;
   case STATE_SCANING:
    drawWhiteCircle(canvas);
    drawBlueCircle(canvas);
    drawInsiderRedCircle(canvas);
    drawOutsiderRedCircle(canvas);
    drawScaner(canvas);
    break;
   case STATE_SUCCESS:
    drawWhiteCircle(canvas);
    drawInsiderRedCircle(canvas);
    break;
  }
  updateValues();
  invalidate();
 }

 private int blueStartAngle = 0;//蓝色圆圈的开始角度
 private int blueCircleSpace = BLUE_CIRCLE_BORDER_WIDTH;//蓝色弧距离最短边的距离用于计算自身的半径用
 private static final int BLUE_CIRCLE_SWEP_ANGLE = 20;//蓝色弧扫过的角度

 /**
  * 绘制蓝色弧
  * @param canvas
  */
 private void drawBlueCircle(Canvas canvas) {
  canvas.drawArc(centerX - radius + blueCircleSpace, blueCircleSpace, centerX + radius - blueCircleSpace, minLength - blueCircleSpace, blueStartAngle, BLUE_CIRCLE_SWEP_ANGLE, false, blueCirclePaint);
  canvas.drawArc(centerX - radius + blueCircleSpace, blueCircleSpace, centerX + radius - blueCircleSpace, minLength - blueCircleSpace, blueStartAngle + 180, BLUE_CIRCLE_SWEP_ANGLE, false, blueCirclePaint);
 }

 /**
  * 根据当前的状态来更改变量达到动画的效果
  */
 private void updateValues() {
  switch (curState) {
   case STATE_READY:
    if (insideRedCircleSpace >= BLUE_CIRCLE_BORDER_WIDTH + INSIDER_RED_CIRCLE_BORDER_WIDTH+ OUTSIDER_CIRCLE_BORDER_WIDTH) {
     insideRedCircleSpace -= 2;
    }
    whiteStartAngle = 5 / 2;
    outsiderRedCircleStartAndle = -OUTSIDER_RED_CIRCLE_SWEP_ANGLE / 2;
    break;
   case STATE_SCANING:
    if (insideRedCircleSpace >= BLUE_CIRCLE_BORDER_WIDTH + INSIDER_RED_CIRCLE_BORDER_WIDTH+ OUTSIDER_CIRCLE_BORDER_WIDTH) {
     insideRedCircleSpace -= 2;
    }
    blueStartAngle += 4;
    outsiderRedCircleStartAndle += 2;
    if (is2Max) {
     if (whiteStartAngle == 30) {
      is2Max = false;
     } else {
      whiteStartAngle++;
     }
    } else {
     if (whiteStartAngle == -30) {
      is2Max = true;
     } else {
      whiteStartAngle--;
     }
    }
    scanerY += 6;
    if (scanerY > minLength) {
     scanerY = 0;
    }
    break;
   case STATE_SUCCESS:
    whiteStartAngle = 5 / 2;
    if (insideRedCircleSpace < whiteCircleSpace + INSIDER_RED_CIRCLE_BORDER_WIDTH) {
     insideRedCircleSpace += 2;
    }
    break;
  }
 }

 private int insideRedCircleSpace = BLUE_CIRCLE_BORDER_WIDTH + INSIDER_RED_CIRCLE_BORDER_WIDTH + OUTSIDER_CIRCLE_BORDER_WIDTH;
 private int outsiderRedCircleSpace = BLUE_CIRCLE_BORDER_WIDTH + INSIDER_RED_CIRCLE_BORDER_WIDTH + OUTSIDER_CIRCLE_BORDER_WIDTH / 2;
 private static final int OUTSIDER_RED_CIRCLE_SWEP_ANGLE = 30;
 private int outsiderRedCircleStartAndle = -OUTSIDER_RED_CIRCLE_SWEP_ANGLE / 2;

 /**
  * 绘制内部的红色圆圈
  * @param canvas
  */
 private void drawInsiderRedCircle(Canvas canvas) {
  canvas.drawCircle(centerX, centerY, radius - insideRedCircleSpace, redCirclePaint);
 }

 /**
  * 绘制外部红色的两个弧
  * @param canvas
  */
 private void drawOutsiderRedCircle(Canvas canvas) {
  canvas.drawArc(centerX - radius + outsiderRedCircleSpace, outsiderRedCircleSpace, centerX + radius - outsiderRedCircleSpace, minLength - outsiderRedCircleSpace, outsiderRedCircleStartAndle, OUTSIDER_RED_CIRCLE_SWEP_ANGLE, false, redCirclePaint);
  canvas.drawArc(centerX - radius + outsiderRedCircleSpace, outsiderRedCircleSpace, centerX + radius - outsiderRedCircleSpace, minLength - outsiderRedCircleSpace, outsiderRedCircleStartAndle + 180, OUTSIDER_RED_CIRCLE_SWEP_ANGLE, false, redCirclePaint);
 }

 private int whiteStartAngle = 0;
 private static final int WHITE_CIRCLE_SWEP_ANGLE = 85;
 private int whiteCircleSpace = BLUE_CIRCLE_BORDER_WIDTH + INSIDER_RED_CIRCLE_BORDER_WIDTH + OUTSIDER_CIRCLE_BORDER_WIDTH + WHITE_CIRCLE_BORDER_WIDTH;
 private RectF whiteCircleRect;
 private boolean is2Max = true;

 /**
  * 绘制白色的弧
  * @param canvas
  */
 private void drawWhiteCircle(Canvas canvas) {
  if (whiteCircleRect == null) {
   whiteCircleRect = new RectF(centerX - radius + whiteCircleSpace, whiteCircleSpace, centerX + radius - whiteCircleSpace, minLength - whiteCircleSpace);
  }

  canvas.drawArc(whiteCircleRect, whiteStartAngle, WHITE_CIRCLE_SWEP_ANGLE, false, whiteCirclePaint);
  canvas.drawArc(whiteCircleRect, whiteStartAngle + 90, WHITE_CIRCLE_SWEP_ANGLE, false, whiteCirclePaint);
  canvas.drawArc(whiteCircleRect, whiteStartAngle + 180, WHITE_CIRCLE_SWEP_ANGLE, false, whiteCirclePaint);
  canvas.drawArc(whiteCircleRect, whiteStartAngle + 270, WHITE_CIRCLE_SWEP_ANGLE, false, whiteCirclePaint);

 }

 private int scanerY = 0;

 /**
  * 绘制扫描图片
  * @param canvas
  */
 private void drawScaner(Canvas canvas) {

  int p1, p2, hw;
  if (scanerY >= radius) {
   p1 = (scanerY - radius) * (scanerY - radius);
  } else {
   p1 = (radius - scanerY) * (radius - scanerY);
  }
  p2 = radius * radius;
  hw = (int) Math.sqrt(p2 - p1);

  Rect rect = new Rect(centerX - hw, scanerY - 10, centerX + hw, scanerY + 10);
  canvas.drawBitmap(scanerbitmap, null, rect, null);

 }
}

下面是我偶读github地址

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android中加入名片扫描功能实例代码

    要想实现android手机通过扫描名片,得到名片信息,可以使用脉可寻提供的第三方SDK,即Maketion ScanCard SDK,脉可寻云名片识别服务.他们的官方网站为http://www.maketion.com/. 一.概述 Maketion ScanCardSDK(以下简称SDK)是提供给第三方合作伙伴接入脉可寻云名片识别服务,合作伙伴需要先申请key和secure才可以使用. SDK不能独立运行,使用时需要嵌入到Android的Project中. SDK支持Android2.1版本及

  • Android扫描本地音乐文件开发案例分享

    一.前言 本来觉得so easy,真是没想到,还搞了老半天,搞的我大汗淋漓,要拍桌子摔键盘了. 本想实现的功能是: 通过网易云音乐/百度音乐/QQ音乐/酷狗音乐中一个API,通过关键词/歌手/歌词来搜索相关歌曲信息,然后在线播放.下载到本地,不过目前来看,使用API还是有一点问题.通过浏览器访问,问题不大,例如下图: 但是想通过手机访问的时候,问题就出现了,同样的参数,结果很不一样,而且基本搜不到自己想要的,后来换做通过自己的服务器去访问,还是搜不到,后来查了一下资料,暂时也没解决.于是,目前就

  • Android基于google Zxing实现各类二维码扫描效果

    随着微信的到来,二维码越来越火爆,随处能看到二维码,比如商城里面,肯德基,餐厅等等,对于二维码扫描我们使用的是google的开源框架Zxing,我们可以去http://code.google.com/p/zxing/下载源码和Jar包,之前我项目中的二维码扫描功能只实现了扫描功能,其UI真的是其丑无比,一个好的应用软件,其UI界面也要被大众所接纳,不然人家就不会用你的软件啦,所以说应用软件功能和界面一样都很重要,例如微信,相信微信UI被很多应用软件所模仿,我也仿照微信扫描二维码效果进行模仿,虽然

  • Android app第三方支付宝支付接入教程

    支付宝的接入相对比较简单,看看支付宝官网的文档基本都能搞定,但是切记一点让你们的后台也要搞清楚支付宝的流程,重中之重. 1.注意事项 开发前一定要阅读支付宝官方文档 强烈建议签名等处理在后台处理,我这个是测试是在自己本地写的,不要吐槽 想获取支付宝合作商户ID,及支付宝公钥请点击支付宝链接,生成密钥及PKCS8转码工具在文档中 添加Android.permission.INTERNET权限和android.permission.ACCESS_NETWORK_STATE权限 要导入支付宝的包 2.

  • Android基于zxing的二维码(网格)扫描 仿支付宝网格扫描

    前言:对于二维码扫描我们使用的是开源框架Zxing或者Zbar,这里使用基于zxing的二维码扫描,类似支付宝网格扫描. 二维码原理介绍: 二维码是用某种特定的几何图形按一定的规律在平面上分布的黑白相间的图形记录数据符号信息的,在代码编制上巧妙的利用构成计算机内部逻辑基础的0/1比特流的概念,使用若干个与二进制相对应的几何形体来表示文字数值信息,通过图像输入设备或光电扫描设备自动识读以实现信息自动处理:二维码能够在横向和纵向两个方位同时表达信息,因此能在很小的面积内表达大量的信息. 效果: 真机

  • Android平台生成二维码并实现扫描 & 识别功能

    1.二维码的前世今生 "二维条码/二维码(2-dimensional bar code)是用某种特定的几何图形按一定规律在平面(二维方向上)分布的黑白相间的图形记录数据符号信息的:在代码编制上巧妙地利用构成计算机内部逻辑基础的"0"."1"比特流的概念,使用若干个与二进制相对应的几何形体来表示文字数值信息,通过图象输入设备或光电扫描设备自动识读以实现信息自动处理:它具有条码技术的一些共性:每种码制有其特定的字符集:每个字符占有一定的宽度:具有一定的校验功能

  • Android开发框架之自定义ZXing二维码扫描界面并解决取景框拉伸问题

    先给大家展示下效果图: 扫描内容是下面这张,二维码是用zxing库生成的 由于改了好几个类,还是去年的事都忘得差不多了,所以只能上这个类的代码了,主要就是改了这个CaptureActivity.java package com.zxing.activity; import java.io.IOException; import java.util.Vector; import android.app.Activity; import android.content.Intent; import

  • Android波纹扩散效果之仿支付宝咻一咻功能实现波纹扩散特效

    今年春节晚会没看尽兴,被支付宝集福给添了一段插曲,朋友们都在那数定时间段不停的咻一咻,哇,我咻到一个敬业福,不可能的,哈哈.那么咻一咻功能基于程序代码是怎么实现的呢?下面我们小编给大家分享本教程帮助大家学习Android波纹扩散效果之仿支付宝咻一咻功能实现波纹扩散特效,具体内容如下所示: 先来看看这个效果 这是我的在Only上添加的效果,说实话,Only现在都还只是半成品,台面都上不了,怪自己技术不行,也太懒了 PS:这个view也是我模仿了人家的效果,参考了人家的思路写的,不是纯手撸,罪过罪过

  • Android应用中使用ContentProvider扫描本地图片并显示

    之前群里面有朋友问我,有没有关于本地图片选择的Demo,类似微信的效果,他说网上没有这方面的Demo,问我能不能写一篇关于这个效果的Demo,于是我研究了下微信的本地图片选择的Demo,自己仿照的写了下分享给大家,希望对以后有这样子需求的朋友有一点帮助吧,主要使用的是ContentProvider扫描手机中的图片,并用GridView将图片显示出来,关于GridView和ListView显示图片的问题,一直是一个很头疼的问题,因为我们手机的内存有限,手机给每个应用程序分配的内存也有限,所以图片多

  • Android实现二维码扫描和生成的简单方法

    这里简单介绍一下ZXing库.ZXing是一个开放源码的,用Java实现的多种格式的1D/2D条码图像处理库,它包含了联系到其他语言的端口.Zxing可以实现使用手机的内置的摄像头完成条形码的扫描及解码.该项目可实现的条形码编码和解码.目前支持以下格式:UPC-A,UPC-E.EAN-8,EAN-13.39码.93码.ZXing是个很经典的条码/二维码识别的开源类库,以前在功能机上,就有开发者使用J2ME运用ZXing了,不过要支持JSR-234规范(自动对焦)的手机才能发挥其威力. ZXing

随机推荐