Android自定義view--雷達掃描

雷達掃描view,先看下整體效果:

項目地址https://github.com/buder-cp/CustomView/blob/master/buder_DN_view/buderdn03/src/main/java/com/test/buderdn03/RadarGradientView.java

 準備兩個畫筆,一個是一圈圈的圓圈,另一個是掃描畫筆;

動畫實現

這裏實現動畫的時候,用到了Matrix這個東西,也就是矩陣。上學的時候,線性代數老師講各種線性變換時,腦子裏在想,這玩意是幹嘛使得,現在總算是遇上了,現在看起來也是雲裏霧裏。總的來說就是可以使用Matrix實現強大的圖形動畫,包括位移、旋轉、縮放及透明變化等效果,matrix有着一系列的setTranslate,setRotate,setScale等方法。很方便的實現圖形各種變換,主要還是需要理解各種變換。

核心的雷達掃描動畫是利用了Matrix的Rotate函數。對Matrix有興趣的同學可以深入研究一下,這篇博客對此講的很仔細

代碼實現:

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Shader;
import android.graphics.SweepGradient;
import android.util.AttributeSet;
import android.view.View;

import androidx.annotation.Nullable;

public class RadarGradientView extends View {

    private int mWidth, mHeight;

    //五個圓
    private float[] pots = {0.05f, 0.1f, 0.15f, 0.2f, 0.25f};

    private Matrix matrix = new Matrix(); // 旋轉需要的矩陣

    private Paint mPaintCircle; // 畫圓用到的paint
    private Paint mPaintRadar; // 掃描用到的paint

    public RadarGradientView(Context context) {
        super(context);
        // 畫圓用到的paint
        mPaintCircle = new Paint();
        mPaintCircle.setStyle(Paint.Style.STROKE); // 描邊
        mPaintCircle.setStrokeWidth(3); // 寬度
        mPaintCircle.setAlpha(20); // 透明度
        mPaintCircle.setAntiAlias(true); // 抗鋸齒
        mPaintCircle.setColor(Color.parseColor("#B0C4DE")); // 設置顏色 亮鋼蘭色
        // 掃描用到的paint
        mPaintRadar = new Paint();
        mPaintRadar.setStyle(Paint.Style.FILL_AND_STROKE); // 填充
        mPaintRadar.setAntiAlias(true); // 抗鋸齒

        post(run);
    }

    public RadarGradientView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public RadarGradientView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        // 取屏幕的寬高是爲了把雷達放在屏幕的中間
        mWidth = getMeasuredWidth();
        mHeight = getMeasuredHeight();
        mWidth = mHeight = Math.min(mWidth, mHeight);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        for (int i = 0; i < pots.length; i++) {
            canvas.drawCircle(mWidth / 2, mHeight / 2, mWidth * pots[i], mPaintCircle);
        }

        // 畫布的旋轉變換 需要調用save() 和 restore()
        canvas.save();

        // 掃描渲染shader
        Shader scanShader = new SweepGradient(mWidth / 2, mHeight / 2,
                new int[]{Color.TRANSPARENT, Color.parseColor("#84B5CA")}, null);
        mPaintRadar.setShader(scanShader); // 設置着色器
        canvas.concat(matrix);
        canvas.drawCircle(mWidth / 2, mHeight / 2, mWidth * pots[4], mPaintRadar);

        canvas.restore();
    }

    private Runnable run = new Runnable() {
        @Override
        public void run() {
            int scanSpeed = 1; // 掃描速度
            matrix.postRotate(scanSpeed, mWidth / 2, mHeight / 2); // 旋轉矩陣
            invalidate(); // 通知view重繪
            postDelayed(run, 10); // 調用自身 重複繪製
        }
    };
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章