最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android實現(xiàn)支付寶AR掃描動畫效果

 更新時間:2018年02月09日 10:50:12   作者:噠噠哈哈丶  
這篇文章主要為大家詳細介紹了Android實現(xiàn)支付寶AR掃描動畫效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下

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

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

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

這個自定義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坐標(biāo)
 private int centerY;//中心點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)方便后面的計算
  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;//藍色圓圈的開始角度
 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);
 }

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

 /**
  * 繪制外部紅色的兩個弧
  * @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地址

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Android Handler實現(xiàn)閃屏頁倒計時代碼

    Android Handler實現(xiàn)閃屏頁倒計時代碼

    這篇文章主要介紹了Android Handler實現(xiàn)閃屏頁倒計時代碼,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-08-08
  • android studio的使用sdk manager的方法

    android studio的使用sdk manager的方法

    這篇文章主要介紹了android studio的使用sdk manager的方法,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • Android 仿京東商城底部布局的選擇效果(Selector 選擇器的實現(xiàn))

    Android 仿京東商城底部布局的選擇效果(Selector 選擇器的實現(xiàn))

    這篇文章主要介紹了Android 仿京東商城底部布局的選擇效果(Selector 選擇器的實現(xiàn)),需要的朋友可以參考下
    2017-04-04
  • Android自定義流式布局的實現(xiàn)示例

    Android自定義流式布局的實現(xiàn)示例

    這篇文章主要介紹了Android自定義流式布局的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • Android Universal ImageLoader 緩存圖片

    Android Universal ImageLoader 緩存圖片

    Universal Image Loader for Android的目的是為了實現(xiàn)異步的網(wǎng)絡(luò)圖片加載、緩存及顯示,支持多線程異步加載,通過本文給大家介紹Android Universal ImageLoader緩存圖片相關(guān)資料,涉及到imageloader緩存圖片相關(guān)知識,對imageloader緩存圖片相關(guān)知識感興趣的朋友一起學(xué)習(xí)
    2016-01-01
  • Android利用Paint自定義View實現(xiàn)進度條控件方法示例

    Android利用Paint自定義View實現(xiàn)進度條控件方法示例

    這篇文章主要給大家介紹了關(guān)于Android利用Paint自定義View實現(xiàn)進度條控件的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對各位Android開發(fā)者們具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-11-11
  • android通過Location API顯示地址信息的實現(xiàn)方法

    android通過Location API顯示地址信息的實現(xiàn)方法

    這篇文章主要介紹了android通過Location API顯示地址信息的方法,涉及Android操作Geocoder類獲取地址信息的相關(guān)技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-07-07
  • Android實現(xiàn)自定義帶刪除功能的EditText實例

    Android實現(xiàn)自定義帶刪除功能的EditText實例

    本篇文章主要介紹了Android實現(xiàn)自定義帶刪除功能的EditText實例,非常具有實用價值,需要的朋友可以參考下
    2017-06-06
  • Android RecyclerView實現(xiàn)下拉刷新和上拉加載更多

    Android RecyclerView實現(xiàn)下拉刷新和上拉加載更多

    這篇文章主要為大家詳細介紹了Android RecyclerView實現(xiàn)下拉刷新和上拉加載更多,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-02-02
  • 完全解析Android多線程中線程池ThreadPool的原理和使用

    完全解析Android多線程中線程池ThreadPool的原理和使用

    本篇文章給大家通過原理和實例詳細講述了Android多線程中線程池ThreadPool的原理和使用,對此有興趣的朋友可以跟著參考學(xué)習(xí)下。
    2018-04-04

最新評論

安岳县| 三门县| 喀喇沁旗| 隆安县| 桐柏县| 临漳县| 轮台县| 翁牛特旗| 娄底市| 库尔勒市| 梁平县| 宁夏| 吴忠市| 松原市| 灵山县| 汽车| 木兰县| 曲阜市| 从化市| 铜川市| 昭平县| 江津市| 镇赉县| 徐水县| 克东县| 昭苏县| 云阳县| 伊金霍洛旗| 诸城市| 张家口市| 邢台市| 凤山县| 瓦房店市| 新余市| 灵武市| 得荣县| 阳西县| 中西区| 鲁甸县| 高安市| 罗甸县|