您的位置:首页 > 移动开发 > Android开发

Android 雷达扫描效果

2015-09-25 23:45 615 查看
    第一个实例 RadarView 用到了自定义属性,然后在构造方法里面读取相关属性值,用来确定绘制的参数
。RadarView 还提供了开始、停止扫描和释放资源的接口,具体实现看源码吧 。要注意的是 onDraw() 是频繁调用的方法,而且绘制过程比较耗时,所以尽量不要在这个方法里做初始化资源的操作,以确保自定义 View 的流畅体验 。同时,在 Activity 被销毁的时候,要停止 RadarView 里边的定时刷新线程,这一点不要漏掉了 。RadarView 源码

/**
* Created by StormShadow on 2015/9/24:20:23.
* Knowledge is power.
*/
public class RadarView extends View {
private static final String LOG_TAG = RadarView.class.getName();
private boolean mIsShowText = true;
// private int mScreenWidth = 0;
private float mRectWidth = 0;
private float mRectHeight = 0;
private float mPadding = 0;
private float mCurAngle = 0; // 扇形当前的偏转角
private Boolean mScanFlag = true;
private Boolean mIsActivityDestoryed = false;
private Bitmap mBgBitmap;
private Rect mSrcRect;
private RectF mDesRectF;
private Paint mBgPaint;
private Paint mSectorPaint; // 画扇形的画笔
float mBigCircleRadius; // 大圆半径
float mCircleX; // 圆心 X 坐标
float mCircleY; // 圆心 Y 坐标
public RadarView(Context context) {
this(context, null);
}
public RadarView(Context context, AttributeSet attrs){
super(context, attrs);
TypedArray array = context.getTheme().obtainStyledAttributes(
attrs,
R.styleable.RadarView,
0, 0);
try {
mIsShowText = array.getBoolean(R.styleable.RadarView_isShowText, true); // 是否显示文字信息
mPadding = array.getDimension(R.styleable.RadarView_labelPadding, 20.0f); // 边距
mRectWidth = array.getDimension(R.styleable.RadarView_labelWidth, 720.0f); // 背景矩形宽度
// mRectHeight = array.getDimension(R.styleable.RadarView_labelHeight, 0.0f); // 为了防止变形,这里强制使高宽相等
mRectHeight = mRectWidth;
} finally {
array.recycle();
}
setBackgroundColor(0xff2a73b1);
init();
}
private void init() {
// mHandler = new Handler();
mBgPaint = new Paint();
mBgBitmap = BitmapFactory.decodeResource(this.getContext().getResources(), R.mipmap.act_radar_bg);
mBigCircleRadius = (mRectWidth - mPadding * 2) / 2; // 大圆半径
mCircleX = mRectWidth / 2; // 圆心 X 坐标
mCircleY = mRectHeight / 2; // 圆心 Y 坐标
mSrcRect = new Rect(
0,
0,
mBgBitmap.getWidth(),
mBgBitmap.getHeight()
);
mDesRectF = new RectF(
mCircleX - mBigCircleRadius,
mCircleY - mBigCircleRadius,
mCircleX + mBigCircleRadius,
mCircleY + mBigCircleRadius
);
mSectorPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mSectorPaint.setStyle(Paint.Style.FILL);
mSectorPaint.setColor(0x7f99cc99); // 半透明,所以设置为7f 99cc99
Shader mShader = new LinearGradient(0, 0, 100, 100,
new int[] { Color.GREEN, Color.GREEN },
null,
Shader.TileMode.REPEAT); // 一个材质,打造出一个线性梯度沿著一条线。
mSectorPaint.setShader(mShader);
ScanThread scanThread = new ScanThread();
scanThread.start();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(mBgBitmap, mSrcRect, mDesRectF, mBgPaint);
canvas.drawArc(mDesRectF, mCurAngle, 45, true, mSectorPaint);
}
public void startScanning() {
if(!mScanFlag) {
mScanFlag = true;
}
}
public void stopScanning() {
if(mScanFlag) {
Thread.interrupted();
mScanFlag = false;
}
}
protected class ScanThread extends Thread {
@Override
public void run() {
while(!mIsActivityDestoryed) {
if (mScanFlag) {
try {
Thread.sleep(10);
mCurAngle = (mCurAngle + 1) % 360;
postInvalidate();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
public void setIsShowText(boolean showText) {
mIsShowText = showText;
invalidate();
}
public Boolean getIsShowText() {
return mIsShowText;
}
public Boolean isScanning() {
return mScanFlag;
}
public void realseResource() {
Thread.interrupted();
mIsActivityDestoryed = true;
}
}
有图有真相



    第二个实例没有自定义属性,而且扫描扇形的旋转操作借助了 Matrix,要注意的是这个实例并没有处理好所有细节 。所以如果要使用它,请参照上面的例子来进行调整 。
这个例子非常简单,只有一个 View 类,继承了 FrameLayout,代码如下
/**
* Created by StormShadow on 2015/9/24:21:35.
* Knowledge is power.
*/
public class RadarView extends FrameLayout {

private int mViewSize = 500;
private Paint mPaintLine;
private Paint mPaintSector;
private boolean mIsStarted = false;
private ScanThread mThread;
private int mCurAngle = 0;
private Shader mShader;
private Matrix mMatrix;

private final int paintWidth = 2;

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

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

private void init() {
initPaint();
mThread = new ScanThread();
setBackgroundColor(Color.TRANSPARENT);

mMatrix = new Matrix();
mShader = new SweepGradient(
mViewSize >> 1,
mViewSize >> 1,
new int[] {
Color.LTGRAY,
Color.GREEN,
},
null);
}

private void initPaint() {
mPaintLine = new Paint();
mPaintLine.setStrokeWidth(paintWidth);
mPaintLine.setAntiAlias(true);
mPaintLine.setStyle(Style.STROKE);
mPaintLine.setColor(0xffff0000);

mPaintSector = new Paint();
mPaintSector.setColor(0x9D00ff00);
mPaintSector.setAntiAlias(true);
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(mViewSize, mViewSize);
}

public void startScanning() {
mThread.start();
mIsStarted = true;
}

public void stopScanning() {
if (mIsStarted) {
Thread.interrupted();
mIsStarted = false;
}
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int halfRadaSize = mViewSize >> 1;
canvas.drawCircle(halfRadaSize, halfRadaSize, halfRadaSize >> 1, mPaintLine);
canvas.drawCircle(halfRadaSize, halfRadaSize, halfRadaSize - (paintWidth >> 1), mPaintLine);
canvas.drawLine(halfRadaSize, 0, halfRadaSize, mViewSize, mPaintLine);
canvas.drawLine(0, halfRadaSize, mViewSize, halfRadaSize, mPaintLine);

mPaintSector.setShader(mShader);
canvas.concat(mMatrix);
canvas.drawCircle(halfRadaSize, halfRadaSize, halfRadaSize - paintWidth, mPaintSector);
}

protected class ScanThread extends Thread {

int halfRadaSize = mViewSize >> 1;

@Override
public void run() {
while (mIsStarted) {
mCurAngle = (mCurAngle + 2) % 360;
mMatrix.reset();
mMatrix.postRotate(mCurAngle, halfRadaSize, halfRadaSize);
postInvalidate();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}


效果图如下



下载源码
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息