溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Android如何實(shí)現(xiàn)支付寶AR掃描動(dòng)畫效果

發(fā)布時(shí)間:2021-04-17 10:25:13 來源:億速云 閱讀:282 作者:小新 欄目:移動(dòng)開發(fā)

這篇文章將為大家詳細(xì)講解有關(guān)Android如何實(shí)現(xiàn)支付寶AR掃描動(dòng)畫效果,小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。

支付寶AR掃描效果動(dòng)畫實(shí)現(xiàn),具體內(nèi)容如下

之前一個(gè)網(wǎng)友說想要一個(gè)支付寶掃描動(dòng)畫的效果demo,所以又花了點(diǎn)時(shí)間做了下這個(gè)東西,先看效果圖

Android如何實(shí)現(xiàn)支付寶AR掃描動(dòng)畫效果

說一下實(shí)現(xiàn)的思路,如圖中最外圍的藍(lán)色的是用兩個(gè)相距180°的圓弧實(shí)現(xiàn)的,再往里又是兩個(gè)紅色的圓弧再往里面是一個(gè)紅色的圓,最里面的白色的是由4個(gè)間隔的白色圓弧組成的,其實(shí)說明白的就是簡(jiǎn)單的圖形的堆積.然后通過控制繪制圓弧的起始角度進(jìn)行旋轉(zhuǎn)的動(dòng)畫.掃描的紅色線條是一張漸變的圖片,通過平移動(dòng)畫實(shí)現(xiàn)掃描的效果.

這個(gè)自定義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;//藍(lán)色圈的畫筆
 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;//中心點(diǎn)X坐標(biāo)
 private int centerY;//中心點(diǎn)Y坐標(biāo)

 private Bitmap scanerbitmap;//條形掃描圖片
 private int curState = STATE_SCANING;//初始狀態(tài)

 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;
  //獲取直徑和半徑以及中心帶你坐標(biāo)方便后面的計(jì)算
  minLength = Math.min(width, height);
  radius = minLength / 2;

 }


 /**
  * 公開方法設(shè)置當(dāng)前的狀態(tài)值
  * @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;//藍(lán)色圓圈的開始角度
 private int blueCircleSpace = BLUE_CIRCLE_BORDER_WIDTH;//藍(lán)色弧距離最短邊的距離用于計(jì)算自身的半徑用
 private static final int BLUE_CIRCLE_SWEP_ANGLE = 20;//藍(lán)色弧掃過的角度

 /**
  * 繪制藍(lán)色弧
  * @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);
 }

 /**
  * 根據(jù)當(dāng)前的狀態(tài)來更改變量達(dá)到動(dòng)畫的效果
  */
 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;

 /**
  * 繪制內(nèi)部的紅色圓圈
  * @param canvas
  */
 private void drawInsiderRedCircle(Canvas canvas) {
  canvas.drawCircle(centerX, centerY, radius - insideRedCircleSpace, redCirclePaint);
 }

 /**
  * 繪制外部紅色的兩個(gè)弧
  * @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);

 }
}

關(guān)于“Android如何實(shí)現(xiàn)支付寶AR掃描動(dòng)畫效果”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,使各位可以學(xué)到更多知識(shí),如果覺得文章不錯(cuò),請(qǐng)把它分享出去讓更多的人看到。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI