记的之前看到一个通过扫描渲染实现的雷达效果UI。自己在复习shader,在此做一个记录。
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();
}
}
}
布局文件