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,代码如下
效果图如下
下载源码
。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(); } } } } }
效果图如下
下载源码
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题