自定义View-简易雷达扫描
简易雷达扫描效果图,实际效果比这个要好,gif生成时或者网页渲染这个gif有点问题。

原理:
- drawCircle画2个同心圆 内圆和外圆
- drawLine画2条直径,水平和垂直的
- drawArc画弧
- 起始角度每次增大4°,从0°开始。
- 每次画弧的起始角度相对于上一次增大4°,通过旋转坐标系来实现,开始为0°,360°后转为0°. 保存初始坐标系,旋转后恢复到开始的坐标系(3点钟为0°方向)
- 每次画弧的终点角度相对于上一次增大4°,直到360°后由重0°开始
- 弧的画笔通过SweepGradient设置渐变色
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.SweepGradient;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.View;
import com.bytedance.xly.R;
public class RadarScanView extends View {
private static final int MSG_RUN = 1;
private int mCircleColor = Color.BLACK;
private int mLineColor = Color.BLACK;
private int mArcColor = Color.WHITE;
private int mArcStartColor = Color.WHITE;
private int mArcEndColor = Color.TRANSPARENT;
private Paint mCirclePaint; // 绘制圆形画笔
private Paint mArcPaint; // 绘制扇形画笔
private Paint mLinePaint; // 绘制线条画笔
private RectF mRectF;
private int mSweep; // 扇形角度
public RadarScanView(Context context) {
this(context, null);
}
public RadarScanView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public RadarScanView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
/**
* 初始化
*/
private void init(Context context){
mCircleColor = context.getResources().getColor(R.color.radar_begin_color);
mArcColor = context.getResources().getColor(R.color.radar_begin_color);
mLineColor = context.getResources().getColor(R.color.radar_begin_color);
mArcStartColor = context.getResources().getColor(R.color.radar_begin_color);
mArcEndColor = context.getResources().getColor(android.R.color.transparent);
//抗锯齿
mCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mArcPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mCirclePaint.setColor(mCircleColor);
mCirclePaint.setStyle(Paint.Style.STROKE);
mCirclePaint.setStrokeWidth(1.f);
mArcPaint.setColor(mArcColor);
mArcPaint.setStyle(Paint.Style.FILL);
mLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mLinePaint.setColor(mLineColor);
mLinePaint.setStrokeWidth(1.f);
mRectF = new RectF();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int size = getMeasuredWidth();
setMeasuredDimension(size, size);
mRectF.set(0, 0, getMeasuredWidth(), getMeasuredHeight());
mArcPaint.setShader(new SweepGradient(size / 2, size / 2, mArcStartColor, mArcEndColor));
}
@Override
protected void onDraw(Canvas canvas) {
int centerX = getMeasuredWidth() / 2;
int centerY = getMeasuredHeight() / 2;
//保存当前状态
canvas.save();
//选择坐标系
canvas.rotate(mSweep, centerX, centerY);
//画圆弧
canvas.drawArc(mRectF, 0, mSweep, true, mArcPaint);
//恢复到上次保存的状态,这样的结果每次坐标系起点都是3点钟方向,因为mSweep初始为0
canvas.restore();
canvas.drawLine(0, centerY, getMeasuredWidth(), centerY, mLinePaint);
canvas.drawLine(centerX, 0, centerX, getMeasuredHeight(), mLinePaint);
canvas.drawCircle(centerX, centerY, centerX / 2, mCirclePaint);
canvas.drawCircle(centerX, centerY, centerX, mCirclePaint);
}
private boolean swicth = true;
private Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
if(msg.what == MSG_RUN) {
mSweep+=4;
if(mSweep > 360) mSweep = 0;
postInvalidate();
// sendEmptyMessage(MSG_RUN);
if (swicth){
sendEmptyMessageDelayed(MSG_RUN, 50);
}
}
}
};
/**
* 开始扫描的方法
*/
public void startScan(){
if(mHandler != null){
swicth = true;
mHandler.obtainMessage(MSG_RUN).sendToTarget();
}
}
/**
* 停止扫描
*/
public void stopScan(){
if(mHandler != null){
swicth = false;
mHandler.obtainMessage(MSG_RUN).sendToTarget();
}
}
}
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!