> Java > java지도 시간 > Android 애니메이션 레이더 스캐닝 효과

Android 애니메이션 레이더 스캐닝 효과

高洛峰
풀어 주다: 2017-01-16 17:18:17
원래의
2325명이 탐색했습니다.

전체적인 감상을 위해 먼저 렌더링부터 살펴보겠습니다

Android 애니메이션 레이더 스캐닝 효과

자, 이해를 돕기 위해 여기서는 애니메이션에서 본 내용을 확대해 보겠습니다. 순서대로

준비

여기에서는 이 간단한 애니메이션 컨트롤을 구현하기 위해 캔버스(캔버스)와 페인트(브러시)를 사용하기로 결정했습니다.

그림에서 볼 수 있듯이 두 개의 교차된 십자선과 여러 개의 원, 그리고 몇 개의 흰색 점이 있습니다. 따라서 먼저 필요한 브러시, 캔버스 및 일부 데이터를 정의하세요.

setBackgroundColor(Color.TRANSPARENT);
 
 //宽度=5,抗锯齿,描边效果的白色画笔
 mPaintLine = new Paint();
 mPaintLine.setStrokeWidth(5);
 mPaintLine.setAntiAlias(true);
 mPaintLine.setStyle(Style.STROKE);
 mPaintLine.setColor(Color.WHITE);
 
 //宽度=5,抗锯齿,描边效果的浅绿色画笔
 mPaintCircle = new Paint();
 mPaintCircle.setStrokeWidth(5);
 mPaintCircle.setAntiAlias(true);
 mPaintCircle.setStyle(Style.FILL);
 mPaintCircle.setColor(0x99000000);
 
 //暗绿色的画笔
 mPaintSector = new Paint();
 mPaintSector.setColor(0x9D00ff00);
 mPaintSector.setAntiAlias(true);
 //定义一个暗绿色的梯度渲染
 mShader = new SweepGradient(viewSize / 2, viewSize / 2,
Color.TRANSPARENT, Color.GREEN);
 mPaintSector.setShader(mShader);
 
 //白色实心画笔
 mPaintPoint=new Paint();
 mPaintPoint.setColor(Color.WHITE);
 mPaintPoint.setStyle(Style.FILL);
 
 //随机生成一些数组点,模拟雷达扫描结果
 point_x = UtilTools.Getrandomarray(15, 300);
 point_y = UtilTools.Getrandomarray(15, 300);
로그인 후 복사

이에 대해 이야기해 보겠습니다. 여기 SweepGradient

SweepGradient의 생성자:

public SweepGradient(float cx, float cy, int[] colors, float[] positions)
로그인 후 복사
public SweepGradient(float cx, float cy, int color0, int color1)
로그인 후 복사

여기서 cx, cy는 원의 중심을 지정하고, color1, color0 또는 colors는 2개 이상의 색상을 사용하는 경우 그라데이션 색상을 지정합니다. 위치를 전달할 수도 있습니다. 각 색상의 상대적 위치를 지정합니다. 위치가 NULL로 설정되면 색상이 고르게 분포됩니다.

기본 그래픽 그리기

canvas.drawCircle(viewSize / 2, viewSize / 2, 350, mPaintCircle);
canvas.drawCircle(viewSize / 2, viewSize / 2, 255, mPaintLine);
canvas.drawCircle(viewSize / 2, viewSize / 2, 125, mPaintLine);
canvas.drawCircle(viewSize / 2, viewSize / 2, 350, mPaintLine);
//绘制两条十字线
canvas.drawLine(viewSize / 2, 0, viewSize / 2, viewSize, mPaintLine);
canvas.drawLine(0, viewSize / 2, viewSize, viewSize / 2, mPaintLine);
로그인 후 복사

이런 식으로 전체 UI를 그린 후 애니메이션을 추가하여 전체적인 효과를 구현합니다.

애니메이션 구현

여기서 애니메이션을 구현할 때에는 매트릭스인 Matrix를 사용하게 된다. 학교 다닐 때 선형대수학 선생님이 다양한 선형변환에 대해 이야기하실 때 이게 무슨 용도인지 고민하다가 이제야 접하게 됐는데, 이제 구름 속에 있는 것 같습니다. 일반적으로 Matrix를 사용하면 변위, 회전, 크기 조절 및 투명도 변경을 포함한 강력한 그래픽 애니메이션을 얻을 수 있습니다. Matrix에는 일련의 setTranslate, setRotate, setScale 및 기타 메서드가 있습니다. 다양한 그래픽 변형을 구현하는 것이 매우 편리합니다. 가장 중요한 것은 다양한 변형을 이해하는 것입니다.

애니메이션 구현 스레드

protected class ScanThread extends Thread {
 
  private RadarView view;
 
  public ScanThread(RadarView view) {
   // TODO Auto-generated constructor stub
   this.view = view;
  }
 
  @Override
  public void run() {
   // TODO Auto-generated method stub
   while (threadRunning) {
    if (isstart) {
     view.post(new Runnable() {
      public void run() {
       start = start + 1;
       matrix = new Matrix();
       //设定旋转角度,制定进行转转操作的圆心
//       matrix.postRotate(start, viewSize / 2, viewSize / 2);
//       matrix.setRotate(start,viewSize/2,viewSize/2);
       matrix.preRotate(direction*start,viewSize/2,viewSize/2);
       view.invalidate();
 
      }
     });
     try {
      Thread.sleep(5);
     } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
     }
    }
   }
  }
 }
로그인 후 복사

우선 시작은 회전 각도만큼 독립적인 스레드에 연속적으로 누적됩니다. 그런 다음 이를 행렬과 연결합니다. 여기서는 행렬의 3가지 방법을 사용해 보았으나 당분간은 차이가 발견되지 않았습니다.

애니메이션 그리기

그 다음 onDraw 메서드로 계속 그래픽을 그립니다

//根据matrix中设定角度,不断绘制shader,呈现出一种扇形扫描效果
canvas.concat(matrix);
canvas.drawCircle(viewSize / 2, viewSize / 2, 350, mPaintSector);
로그인 후 복사

드디어 달성

자 드디어 전체 코드

public class RadarView extends FrameLayout {
 
 private Context mContext;
 private int viewSize = 800;
 private Paint mPaintLine;
 private Paint mPaintCircle;
 private Paint mPaintSector;
 public boolean isstart = false;
 private ScanThread mThread;
 private Paint mPaintPoint;
 //旋转效果起始角度
 private int start = 0;
 
 private int[] point_x;
 private int[] point_y;
 
 private Shader mShader;
 
 private Matrix matrix;
 
 public final static int CLOCK_WISE=1;
 public final static int ANTI_CLOCK_WISE=-1;
 
 @IntDef({ CLOCK_WISE, ANTI_CLOCK_WISE })
 public @interface RADAR_DIRECTION {
 
 }
 //默认为顺时针呢
 private final static int DEFAULT_DIERCTION=CLOCK_WISE;
 
 //设定雷达扫描方向
 private int direction=DEFAULT_DIERCTION;
 
 private boolean threadRunning = true;
 
 public RadarView(Context context, AttributeSet attrs) {
  super(context, attrs);
  // TODO Auto-generated constructor stub
  mContext = context;
  initPaint();
 }
 
 public RadarView(Context context) {
  super(context);
  // TODO Auto-generated constructor stub
  mContext = context;
  initPaint();
 
 }
 
 private void initPaint() {
  // TODO Auto-generated method stub
  setBackgroundColor(Color.TRANSPARENT);
 
  //宽度=5,抗锯齿,描边效果的白色画笔
  mPaintLine = new Paint();
  mPaintLine.setStrokeWidth(5);
  mPaintLine.setAntiAlias(true);
  mPaintLine.setStyle(Style.STROKE);
  mPaintLine.setColor(Color.WHITE);
 
  //宽度=5,抗锯齿,描边效果的浅绿色画笔
  mPaintCircle = new Paint();
  mPaintCircle.setStrokeWidth(5);
  mPaintCircle.setAntiAlias(true);
  mPaintCircle.setStyle(Style.FILL);
  mPaintCircle.setColor(0x99000000);
 
  //暗绿色的画笔
  mPaintSector = new Paint();
  mPaintSector.setColor(0x9D00ff00);
  mPaintSector.setAntiAlias(true);
  mShader = new SweepGradient(viewSize / 2, viewSize / 2, Color.TRANSPARENT, Color.GREEN);
  mPaintSector.setShader(mShader);
 
  //白色实心画笔
  mPaintPoint=new Paint();
  mPaintPoint.setColor(Color.WHITE);
  mPaintPoint.setStyle(Style.FILL);
 
  //随机生成的点,模拟雷达扫描结果
  point_x = UtilTools.Getrandomarray(15, 300);
  point_y = UtilTools.Getrandomarray(15, 300);
 
 }
 
 public void setViewSize(int size) {
  this.viewSize = size;
  setMeasuredDimension(viewSize, viewSize);
 }
 
 @Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  // TODO Auto-generated method stub
  setMeasuredDimension(viewSize, viewSize);
 }
 
 public void start() {
  mThread = new ScanThread(this);
  mThread.setName("radar");
  mThread.start();
  threadRunning = true;
  isstart = true;
 }
 
 public void stop() {
  if (isstart) {
   threadRunning = false;
   isstart = false;
  }
 }
 
 @Override
 protected void onDraw(Canvas canvas) {
  // TODO Auto-generated method stub
  canvas.drawCircle(viewSize / 2, viewSize / 2, 350, mPaintCircle);
  canvas.drawCircle(viewSize / 2, viewSize / 2, 255, mPaintLine);
  canvas.drawCircle(viewSize / 2, viewSize / 2, 125, mPaintLine);
  canvas.drawCircle(viewSize / 2, viewSize / 2, 350, mPaintLine);
  //绘制两条十字线
  canvas.drawLine(viewSize / 2, 0, viewSize / 2, viewSize, mPaintLine);
  canvas.drawLine(0, viewSize / 2, viewSize, viewSize / 2, mPaintLine);
 
 
  //这里在雷达扫描过制定圆周度数后,将随机绘制一些白点,模拟搜索结果
  if (start > 100) {
   for (int i = 0; i < 2; i++) {
    canvas.drawCircle(viewSize / 2 + point_x[i], viewSize / 2 + point_y[i], 10, mPaintPoint);
   }
  }
  if (start > 200) {
   for (int i = 2; i < 5; i++) {
    canvas.drawCircle(viewSize / 2 + point_x[i], viewSize / 2 + point_y[i], 10, mPaintPoint);
   }
  }
  if (start > 300) {
   for (int i = 5; i < 9; i++) {
    canvas.drawCircle(viewSize / 2 + point_x[i], viewSize / 2 + point_y[i], 10, mPaintPoint);
   }
  }
  if (start > 500) {
   for (int i = 9; i < 11; i++) {
    canvas.drawCircle(viewSize / 2 + point_x[i], viewSize / 2 + point_y[i], 10, mPaintPoint);
   }
  }
  if (start > 800) {
   for (int i = 11; i < point_x.length; i++) {
    canvas.drawCircle(viewSize / 2 + point_x[i], viewSize / 2 + point_y[i], 10, mPaintPoint);
   }
  }
 
  //根据matrix中设定角度,不断绘制shader,呈现出一种扇形扫描效果
  canvas.concat(matrix);
  canvas.drawCircle(viewSize / 2, viewSize / 2, 350, mPaintSector);
  super.onDraw(canvas);
 }
 
 public void setDirection(@RADAR_DIRECTION int direction) {
  if (direction != CLOCK_WISE && direction != ANTI_CLOCK_WISE) {
   throw new IllegalArgumentException("Use @RADAR_DIRECTION constants only!");
  }
  this.direction = direction;
 }
 
 protected class ScanThread extends Thread {
 
  private RadarView view;
 
  public ScanThread(RadarView view) {
   // TODO Auto-generated constructor stub
   this.view = view;
  }
 
  @Override
  public void run() {
   // TODO Auto-generated method stub
   while (threadRunning) {
    if (isstart) {
     view.post(new Runnable() {
      public void run() {
       start = start + 1;
       matrix = new Matrix();
       //设定旋转角度,制定进行转转操作的圆心
//       matrix.postRotate(start, viewSize / 2, viewSize / 2);
//       matrix.setRotate(start,viewSize/2,viewSize/2);
       matrix.preRotate(direction*start,viewSize/2,viewSize/2);
       view.invalidate();
 
      }
     });
     try {
      Thread.sleep(5);
     } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
     }
    }
   }
  }
 }
}
로그인 후 복사

설명

중복되는 부분은 설명하지 않고, 코드에 주석을 명확하게 달았습니다. 이 RadarView의 사용도 매우 간단합니다. 중지해야 할 경우 중지 메소드를 호출하기만 하면 됩니다.

@Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  RadarView radarView = (RadarView) findViewById(R.id.radar);
  //设置雷达扫描方向
  radarView.setDirection(RadarView.ANTI_CLOCK_WISE);
  radarView.start();
 }
로그인 후 복사

여기서 레이더 ViewSize는 800으로 설정되어 있으므로 레이아웃 파일에 크기가 설정되면 작동하지 않습니다. 일반적인 사용 중에는 보기 크기 크기와 여러 원의 반경을 조정해야 합니다. 실제로 더 나은 UI 표시 효과를 달성해야 합니다.

요약

위 내용은 안드로이드의 레이더 스캐닝 효과에 대한 모든 내용입니다. 이 글이 안드로이드 개발에 종사하시는 모든 분들께 도움이 되기를 바랍니다.

안드로이드 애니메이션의 레이더 스캐닝 효과에 대한 더 많은 글은 PHP 중국어 홈페이지를 주목해주세요!

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿