概述
記的之前看到一個通過掃描渲染實現的雷達效果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>
運行效果
希望對您有所幫助!