안 드 로 이 드 애니메이션 레이더 스캐닝 효과

우 리 는 먼저 효과 도 를 보고 전체적인 인상 을 가지 고 있다.

자,이해 하기 편리 하도록 애니메이션 이 보 는 내용 에 따라 순서대로 전개 하 겠 습 니 다.
준비 하 다.
이 간단 한 애니메이션 컨트롤 을 canvas(캔버스)와 paint(붓)로 구현 하기 로 했 습 니 다.
그림 에서 두 개의 교차 하 는 십자선,몇 개의 동그라미 와 흰 점 을 볼 수 있다.그러면 먼저 필요 한 붓,캔버스 와 데 이 터 를 정의 한다.

  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);
여기 스 위 프 그 라 디 언 트.
SweetGradient 의 구조 함수:

public SweepGradient(float cx, float cy, int[] colors, float[] positions)

public SweepGradient(float cx, float cy, int color0, int color1)
그 중에서 cx,cy 는 원심,color 1,color 0 또는 colors 는 그 라 데 이 션 색상 을 지정 합 니 다.두 가지 이상 의 색상 을 사용 할 때 positions 를 통 해 각 색상 의 상대 적 인 위 치 를 지정 할 수 있 습 니 다.positions 는 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();
     }
    }
   }
  }
 }
우선,여 기 는 독립 된 스 레 드 에서 start 를 계속 누적 하여 회전 각도 로 합 니 다.그리고 이 를 matrix 와 연결 합 니 다.matrix 의 세 가지 방법 을 사용 해 보 았 지만 차이 점 은 발견 되 지 않 았 습 니 다.
애니메이션 그리 기
다음 에 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 의 사용 도 간단 합 니 다.멈 춰 야 할 때 stop 방법 을 사용 하면 됩 니 다.

@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();
 }
여기 서 레이더 뷰 사 이 즈 는 800 으로 설정 되 어 있 기 때문에 레이아웃 파일 에 큰 시간 을 설정 하면 작 동 하지 않 습 니 다.정상적으로 사용 할 때 는 실제 수요 에 따라 view size 크기 와 몇 개의 Circle 의 반지름 을 조정 하여 더욱 좋 은 UI 디 스 플레이 효 과 를 얻 을 수 있 습 니 다.
총결산
이상 은 안 드 로 이 드 에서 레이더 스캐닝 효과 가 실 현 된 모든 내용 입 니 다.본 고 는 안 드 로 이 드 개발 에 도움 이 되 기 를 바 랍 니 다.

좋은 웹페이지 즐겨찾기