程序员Android知识

Android下实现雷达扫描效果(学习)

2016-03-29  本文已影响3130人  逐悦

Android UI

  • 初始化几个画笔
private void initPaint() {
    //用来绘画直线的画笔
    mPaintLine = new Paint(Paint.ANTI_ALIAS_FLAG); // 消除锯齿
    mPaintLine.setAntiAlias(true);
    mPaintLine.setColor(Color.WHITE);
    mPaintLine.setStyle(Style.STROKE);
    mPaintLine.setStrokeWidth(5);
    
    //用来绘画背景圆的画笔
    mPaintCircle = new Paint(Paint.ANTI_ALIAS_FLAG);
    mPaintCircle.setAntiAlias(true);
    mPaintCircle.setColor(0x99000000);
    //实心圆style
    mPaintCircle.setStyle(Style.FILL);
    
    //绘画圆渐变色的画笔   
    mPaintSector = new Paint(Paint.ANTI_ALIAS_FLAG);
    mPaintSector.setAntiAlias(true);
    mPaintSector.setStyle(Style.FILL);
    //绘画实点
    mPaintPoint = new Paint(Paint.ANTI_ALIAS_FLAG);
    mPaintPoint.setAntiAlias(true);
    mPaintPoint.setColor(Color.WHITE);
    mPaintPoint.setStyle(Style.FILL);
}
  • 重写了onMeasure函数,在此函数中获得控件的宽度作为雷达的直径

<pre><code>

//重写onMeasure
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    //获得控件的宽度   宽度<=高度
    viewSize = getMeasuredWidth();
    //初始化一个颜色渲染器
    SweepGradient shader = new SweepGradient(viewSize /2.0f, viewSize/2.0f, Color.TRANSPARENT, Color.GREEN);
    //mPaintSector设置颜色渐变渲染器
    mPaintSector.setShader(shader);
}

</code>

  • 然后重写onDraw函数

<code>
@Override
protected void onDraw(Canvas canvas) {

    //绘制背景圆
    canvas.drawCircle(viewSize/2.0f,viewSize/2.0f, viewSize/2.0f, mPaintCircle);
    //绘制空心圆
    canvas.drawCircle(viewSize/2.0f,viewSize/2.0f, viewSize/4.0f, mPaintLine);
    canvas.drawCircle(viewSize/2.0f,viewSize/2.0f, viewSize/8.0f, mPaintLine);
    canvas.drawCircle(viewSize/2.0f,viewSize/2.0f, viewSize/2.0f, mPaintLine);
    //绘制水平垂直两个直径
    canvas.drawLine(0, viewSize/2.0f,viewSize, viewSize/2.0f, mPaintLine);
    canvas.drawLine(viewSize/2.0f,0,viewSize/2.0f,viewSize, mPaintLine);
    
    //可以用来显示实心点,使用了接口让外面调用
    if(mListener != null){
        mListener.OnUpdate(canvas,mPaintPoint,viewSize/2.0f,viewSize/2.0f,viewSize/2.0f);
    }
    
    //把画布的多有对象与matrix联系起来
    if(matrix != null){
        canvas.concat(matrix);
    }
    //绘制颜色渐变圆
    canvas.drawCircle(viewSize/2.0f,viewSize/2.0f, viewSize/2.0f, mPaintSector);
    
    super.onDraw(canvas);
}

</code>

此时的效果显示
  • 然后剩下动画更新了
    在这使用了一个线程来更新界面展示

<code>
class ScanThread extends Thread{
private View view;

    public ScanThread(View view) {
        super();
        this.view = view;
    }

    @Override
    public void run() {
        while(isRunning){
            if(isStart){
                start += 1;
                view.post(new Runnable() {
                    @Override
                    public void run() {
                        //创建一个矩阵
                        matrix = new Matrix();
                        //矩阵设置旋转
                        matrix.preRotate(start*direction, viewSize/2.0f, viewSize/2.0f);
                        //重画
                        view.invalidate();
                    }
                });
                try {
                    Thread.sleep(5);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

</code>

// 需要注意的是,线程的结束和开启是使用了两个boolean的变量来控制
isRunning ,isStart分别表示了线程的状态
view.post(Runable);函数的作用是
Causes the Runnable to be added to the message queue. The runnable will be run on the user interface thread.
意思就是任务会放到ui线程里执行

  • 最后 暴露出一个接口让外界更新发现的目标显示

<code>
public OnPointUpdateListener mListener;

//更新point的接口
public interface OnPointUpdateListener{

//onDraw中的画布,paintPoint绘制实心点的画笔,cx,cy,radius 雷达的圆心坐标,半径
public void OnUpdate(Canvas canvas,Paint paintPoint,float cx,float cy,float radius);
}

public void setOnPointUpdateListener(OnPointUpdateListener listener){

this.mListener = listener;

}
</code>

  • 然后贴出完整的代码

<code>
package com.linge.scanradar.view.radar;

import android.content.Context;

import android.graphics.Canvas;

import android.graphics.Color;

import android.graphics.Matrix;

import android.graphics.Paint;

import android.graphics.SweepGradient;

import android.graphics.Paint.Style;

import android.util.AttributeSet;

import android.view.View;

public class ScanRadar extends View {

//控件宽度<=高度     //雷达直径
private float viewSize;
//画笔
private Paint mPaintSector;
private Paint mPaintCircle;
private Paint mPaintLine;
private Paint mPaintPoint;

//线程是否在执行
private boolean isRunning  = false;
//任务是否已经开始
private boolean isStart = false;

//记录并设置旋转角度
private int start = 0;

//雷达旋转方向  
     //顺时针
public final static int CLOCK_WISE = 1;
    //逆时针
public final static int ANSI_CLOCK_WISE = -1;
public final static int DEFAULT_DIRECTION = CLOCK_WISE;

private int direction = DEFAULT_DIRECTION;

private ScanThread scanThread;  //线程
private Matrix matrix;  //矩阵

public ScanRadar(Context context, AttributeSet attrs) {
    this(context, attrs,0);
}

public ScanRadar(Context context) {
    this(context,null);
}

public ScanRadar(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    
    initPaint();
}

private void initPaint() {

    //用来绘画直线的画笔
    mPaintLine = new Paint(Paint.ANTI_ALIAS_FLAG); // 消除锯齿
    mPaintLine.setAntiAlias(true);
    mPaintLine.setColor(Color.WHITE);
    mPaintLine.setStyle(Style.STROKE);
    mPaintLine.setStrokeWidth(5);
    
    //用来绘画背景圆的画笔
    mPaintCircle = new Paint(Paint.ANTI_ALIAS_FLAG);
    mPaintCircle.setAntiAlias(true);
    mPaintCircle.setColor(0x99000000);
    //实心圆style
    mPaintCircle.setStyle(Style.FILL);
    
    //绘画圆渐变色的画笔
    mPaintSector = new Paint(Paint.ANTI_ALIAS_FLAG);
    mPaintSector.setAntiAlias(true);
    mPaintSector.setStyle(Style.FILL);
    //绘画实点
    mPaintPoint = new Paint(Paint.ANTI_ALIAS_FLAG);
    mPaintPoint.setAntiAlias(true);
    mPaintPoint.setColor(Color.WHITE);
    mPaintPoint.setStyle(Style.FILL);
}

@Override
protected void onDraw(Canvas canvas) {
    
    //绘制背景圆
    canvas.drawCircle(viewSize/2.0f,viewSize/2.0f, viewSize/2.0f, mPaintCircle);
    //绘制空心圆
    canvas.drawCircle(viewSize/2.0f,viewSize/2.0f, viewSize/4.0f, mPaintLine);
    canvas.drawCircle(viewSize/2.0f,viewSize/2.0f, viewSize/8.0f, mPaintLine);
    canvas.drawCircle(viewSize/2.0f,viewSize/2.0f, viewSize/2.0f, mPaintLine);
    //绘制水平垂直两个直径
    canvas.drawLine(0, viewSize/2.0f,viewSize, viewSize/2.0f, mPaintLine);
    canvas.drawLine(viewSize/2.0f,0,viewSize/2.0f,viewSize, mPaintLine);
    
    //显示实心点
    if(mListener != null){
        mListener.OnUpdate(canvas,mPaintPoint,viewSize/2.0f,viewSize/2.0f,viewSize/2.0f);
    }
    
    //把画布的多有对象与matrix联系起来
    if(matrix != null){
        canvas.concat(matrix);
    }
    //绘制颜色渐变圆
    canvas.drawCircle(viewSize/2.0f,viewSize/2.0f, viewSize/2.0f, mPaintSector);
    
    super.onDraw(canvas);
}

//重写onMeasure
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    //获得控件的宽度   宽度<=高度
    viewSize = getMeasuredWidth();
    
    //初始化一个颜色渲染器
    SweepGradient shader = new SweepGradient(viewSize /2.0f, viewSize/2.0f, Color.TRANSPARENT, Color.GREEN);
    //mPaintSector设置颜色渐变渲染器
    mPaintSector.setShader(shader);
}
//设置循环的方向
public void setDirection(int d){
    if(d != CLOCK_WISE && d != ANSI_CLOCK_WISE){
        throw new IllegalStateException("only contonst CLOCK_WISE  ANSI_CLOCK_WISE");
    }
    this.direction = d;
}

//线程开启
public void start(){
    scanThread = new ScanThread(this);
    scanThread.setName("radar");
    isRunning = true;
    isStart = true;
    scanThread.start();
}
//线程结束
public void stop(){
    if(isStart){
        isStart = false;
        isRunning = false;
    }
}
class ScanThread extends Thread{
    private View view;
    
    public ScanThread(View view) {
        super();
        this.view = view;
    }

    @Override
    public void run() {
        while(isRunning){
            if(isStart){
                start += 1;
                view.post(new Runnable() {
                    @Override
                    public void run() {
                        //创建一个矩阵
                        matrix = new Matrix();
                        //矩阵设置旋转
                        matrix.preRotate(start*direction, viewSize/2.0f, viewSize/2.0f);
                        //重画
                        view.invalidate();
                    }
                });
                try {
                    Thread.sleep(5);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}


public OnPointUpdateListener mListener;
//更新point的接口
public interface OnPointUpdateListener{
    public void OnUpdate(Canvas canvas,Paint paintPoint,float cx,float cy,float radius);
}
public void setOnPointUpdateListener(OnPointUpdateListener listener){
    this.mListener = listener;
}

}

//MainActivity中的代码

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    ScanRadar radar = (ScanRadar) findViewById(R.id.scan_radar);
//随机获得一组坐标
    final int[] point_x = getRandomArray(50, 10);
    final int[] point_y = getRandomArray(60, 10);

    radar.setOnPointUpdateListener(new OnPointUpdateListener() {
        @Override
        public void OnUpdate(Canvas canvas, Paint paintPoint, float cx, float cy,
                float radius) {
            for (int i = 0; i < point_y.length; i++) {
                canvas.drawCircle(cx+point_x[i], cy+point_y[i], 5, paintPoint);
            }
        }
    });
    radar.start();
}

</code>

//最后感谢Android 雷达扫描动画效果实现 的作者让我学会了一招

上一篇下一篇

猜你喜欢

热点阅读