Android SweepGradient

概述

記的之前看到一個通過掃描渲染實現的雷達效果UI。自己在複習shader,在此做一個記錄。

SweepGradient 掃描漸變

構造函數參數說明

  public SweepGradient(float cx, float cy, @ColorInt int color0, @ColorInt int color1)

參數(cx,cy)表示掃描渲染所圍繞的圓心點座標,color0 代表渲染的起始顏色,color1代表渲染的結束顏色。

 public SweepGradient(float cx, float cy,
            @NonNull @ColorInt int colors[], @Nullable float positions[]) {

參數(cx,cy)表示掃描渲染所圍繞的圓心點座標,colors數組代表掃描漸變的顏色數組,數組值大於2,第一位數組值代表起始顏色,最後一位代表結束顏色,positinos 數組,每一位值與顏色數組相對應,代表該顏色的渲染起始位置(360*positions[i],具體效果參看示列代碼運行效果圖。

雷達掃描效果

藉助動畫和matrix類不斷旋轉shader的默認顏色渲染角度,形成雷達掃描效果。

示例代碼

掃描渲染view

package com.xol.widget;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.SweepGradient;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;

import com.xol.util.CommonUtil;

/**
 * Created by wwzhang on 2019/3/20
 */
public class SweepGradientView extends View {
    private Paint mPaint;
    private int[] mColorArrayTwo;
    private int[] mColorArrayThree;
    private SweepGradient mSweepGradient;

    public SweepGradientView(Context context) {
        super(context);
    }

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

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

    {
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mColorArrayTwo = new int[]{Color.parseColor("#ff0000"),
                Color.parseColor("#ffffff")};
        mColorArrayThree = new int[]{Color.parseColor("#ff0000")
                , Color.parseColor("#00ff00")
                , Color.parseColor("#0000ff")};

    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //繪製圓形
        mPaint.setStyle(Paint.Style.FILL);
        mSweepGradient = new SweepGradient(200, 200, mColorArrayTwo[0], mColorArrayTwo[1]);
        mPaint.setShader(mSweepGradient);
        canvas.drawCircle(200, 200, 100, mPaint);
        //繪製圓形
        mSweepGradient = new SweepGradient(500, 600, mColorArrayThree, new float[]{0.0f, 0.5f, 1.0f});
        mPaint.setStrokeWidth(CommonUtil.dp2px(4, getContext()));
        mPaint.setStrokeJoin(Paint.Join.ROUND);
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        mPaint.setShader(mSweepGradient);
        canvas.drawCircle(500, 600, 200, mPaint);
        //繪製圓形
        mSweepGradient = new SweepGradient(500, 1000, mColorArrayThree, new float[]{0.5f, 0.75f, 1.0f});
        mPaint.setShader(mSweepGradient);
        canvas.drawCircle(500, 1000, 200, mPaint);

    }
}

雷達掃描view

package com.xol.widget;

import android.animation.ValueAnimator;
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.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.animation.LinearInterpolator;

import com.xol.util.CommonUtil;

/**
 * Created by wwzhang on 2019/3/21
 */
public class RadarView extends View {

    private Paint mPaint;
    private int mCircleColor;
    private int mSweepColor[];
    private float mCenterY;
    private float mCenterX;
    private float mRadius;
    private int mPading;
    private Shader mSweepShader;
    private ValueAnimator mValueAnimator;
    private Matrix mRoateMatrix;
    private float mDegressProgress = 0.2f;

    public RadarView(Context context) {
        super(context);
    }

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

    private static final String TAG = "RadarView";

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

    {
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mRoateMatrix = new Matrix();
        mCircleColor = Color.parseColor("#000000");
        mSweepColor = new int[]{Color.parseColor("#0000ff"),
                Color.parseColor("#22000000")};
        mPaint.setStrokeWidth(CommonUtil.dp2px(2, getContext()));
        mRadius = -1;
        mPading = (int) CommonUtil.dp2px(10, getContext());
        mValueAnimator = ValueAnimator.ofFloat(0, 1.0f);
        mValueAnimator.setInterpolator(new LinearInterpolator());
        mValueAnimator.setRepeatCount(ValueAnimator.INFINITE);
        mValueAnimator.setDuration(5000);
        mValueAnimator.setRepeatMode(ValueAnimator.RESTART);
        mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                mDegressProgress = (float) animation.getAnimatedValue();
                Log.d(TAG, "onAnimationUpdate: " + mDegressProgress);
                invalidate();
            }
        });
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (mRadius < 0) {
            int minDistance = Math.min(getMeasuredHeight(), getMeasuredWidth());
            mCenterX = minDistance / 2;
            mCenterY = mCenterX;
            mRadius = mCenterX - mPading;
            mSweepShader = new SweepGradient(mCenterX, mCenterY, mSweepColor[0], mSweepColor[1]);
        }
        //繪製掃描線
        canvas.save();
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setShader(mSweepShader);
        mRoateMatrix.setRotate(mDegressProgress * 360,mCenterX,mCenterY);
        mSweepShader.setLocalMatrix(mRoateMatrix);
        // canvas.rotate(mDegressProgress * 360, mCenterX, mCenterY);
        canvas.drawCircle(mCenterX, mCenterY, mRadius, mPaint);
        canvas.restore();
        //繪製圓形和直角座標
        mPaint.setColor(mCircleColor);
        mPaint.setShader(null);
        canvas.save();
        mPaint.setStyle(Paint.Style.STROKE);
        canvas.drawCircle(mCenterX, mCenterY, mRadius, mPaint);
        canvas.drawCircle(mCenterX, mCenterY, mRadius / 2, mPaint);
        canvas.drawLine(mPading, mCenterY, mCenterX + mRadius, mCenterY, mPaint);
        canvas.drawLine(mCenterX, mPading, mCenterX, mCenterY + mRadius, mPaint);
        canvas.restore();
        if (!mValueAnimator.isStarted()) {
            mValueAnimator.start();
        }

    }


    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        Log.d(TAG, "onAttachedToWindow: ");
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        Log.d(TAG, "onDetachedFromWindow: ");
        if (mValueAnimator.isStarted()) {
            mValueAnimator.cancel();
        }
    }
}

佈局文件

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.xol.widget.SweepGradientView
        android:id="@+id/sw_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <com.xol.widget.RadarView
        android:layout_gravity="center|bottom"
        android:layout_width="150dp"
        android:layout_height="150dp" />

</FrameLayout>

運行效果

在這裏插入圖片描述
希望對您有所幫助!

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