Android--雷达扫描动态界面

简介: 版权声明:本文为博主原创文章,转载请标明出处。 https://blog.csdn.net/chaoyu168/article/details/52036806 DEMO下载地址:http://download.
版权声明:本文为博主原创文章,转载请标明出处。 https://blog.csdn.net/chaoyu168/article/details/52036806

DEMO下载地址:http://download.csdn.net/detail/chaoyu168/9586664

效果图:

源码:

package com.zihao.radar;

import android.app.Activity;
import android.os.Bundle;
import android.view.Window;
import android.view.WindowManager;

import com.zihao.radar.view.RadarView;

public class MainActivity extends Activity {

	private RadarView mRadarView;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		// 取消状态栏
		getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
				WindowManager.LayoutParams.FLAG_FULLSCREEN);
		setContentView(R.layout.activity_main);
		mRadarView = (RadarView) findViewById(R.id.radar_view);
		mRadarView.setSearching(true);
		mRadarView.addPoint();
		mRadarView.addPoint();
	}

}
package com.zihao.radar.view;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.util.AttributeSet;
import android.view.View;

import com.zihao.radar.R;

/**
 * @ClassName:RadarView
 * @Description:TODO<雷达扫描视图>
 * @author:zihao
 * @date:2015年11月11日 上午12:26:11
 * @version:v1.1
 */
@SuppressLint("DrawAllocation")
public class RadarView extends View {

	private Context mContext;
	private boolean isSearching = false;// 标识是否处于扫描状态,默认为不在扫描状态
	private Paint mPaint;// 画笔
	private Bitmap mScanBmp;// 执行扫描运动的图片
	private int mOffsetArgs = 0;// 扫描运动偏移量参数
	private Bitmap mDefaultPointBmp;// 标识设备的圆点-默认
	private Bitmap mLightPointBmp;// 标识设备的圆点-高亮
	private int mPointCount = 0;// 圆点总数
	private List<String> mPointArray = new ArrayList<String>();// 存放偏移量的map
	private Random mRandom = new Random();
	private int mWidth, mHeight;// 宽高
	int mOutWidth;// 外圆宽度(w/4/5*2=w/10)
	int mCx, mCy;// x、y轴中心点
	int mOutsideRadius, mInsideRadius;// 外、内圆半径

	public RadarView(Context context, AttributeSet attrs, int defStyleAttr) {
		super(context, attrs, defStyleAttr);
		// TODO Auto-generated constructor stub
		init(context);
	}

	public RadarView(Context context, AttributeSet attrs) {
		super(context, attrs);
		// TODO Auto-generated constructor stub
		init(context);
	}

	public RadarView(Context context) {
		super(context);
		// TODO Auto-generated constructor stub
		init(context);
	}

	/**
	 * TODO<提前初始化好需要使用的对象,避免在绘制过程中多次初始化>
	 * 
	 * @return void
	 */
	private void init(Context context) {
		mPaint = new Paint();
		this.mContext = context;
		this.mDefaultPointBmp = Bitmap.createBitmap(BitmapFactory
				.decodeResource(mContext.getResources(),
						R.drawable.radar_default_point_ico));
		this.mLightPointBmp = Bitmap.createBitmap(BitmapFactory.decodeResource(
				mContext.getResources(), R.drawable.radar_light_point_ico));
	}

	/**
	 * 测量视图及其内容,以确定所测量的宽度和高度(测量获取控件尺寸).
	 */
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		// TODO Auto-generated method stub
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);

		// 获取控件区域宽高
		if (mWidth == 0 || mHeight == 0) {
			final int minimumWidth = getSuggestedMinimumWidth();
			final int minimumHeight = getSuggestedMinimumHeight();
			mWidth = resolveMeasured(widthMeasureSpec, minimumWidth);
			mHeight = resolveMeasured(heightMeasureSpec, minimumHeight);
			mScanBmp = Bitmap.createScaledBitmap(BitmapFactory.decodeResource(
					mContext.getResources(), R.drawable.radar_scan_img), mWidth
					- mOutWidth, mWidth - mOutWidth, false);

			// 获取x/y轴中心点
			mCx = mWidth / 2;
			mCy = mHeight / 2;

			// 获取外圆宽度
			mOutWidth = mWidth / 10;

			// 计算内、外半径
			mOutsideRadius = mWidth / 2;// 外圆的半径
			mInsideRadius = (mWidth - mOutWidth) / 4 / 2;// 内圆的半径,除最外层,其它圆的半径=层数*insideRadius
		}
	}

	/**
	 * 绘制视图--从外部向内部绘制
	 */
	@Override
	protected void onDraw(Canvas canvas) {
		// TODO Auto-generated method stub
		super.onDraw(canvas);
		// 开始绘制最外层的圆
		mPaint.setAntiAlias(true);// 设置抗锯齿
		mPaint.setStyle(Style.FILL);// 设置填充样式
		mPaint.setColor(0xffB8DCFC);// 设置画笔颜色
		// 1.开始绘制圆形
		canvas.drawCircle(mCx, mCy, mOutsideRadius, mPaint);

		// 开始绘制内4圆
		mPaint.setColor(0xff3278B4);
		canvas.drawCircle(mCx, mCy, mInsideRadius * 4, mPaint);

		// 开始绘制内3圆
		mPaint.setStyle(Style.STROKE);
		mPaint.setColor(0xff31C9F2);
		canvas.drawCircle(mCx, mCy, mInsideRadius * 3, mPaint);

		// 开始绘制内2圆
		canvas.drawCircle(mCx, mCy, mInsideRadius * 2, mPaint);

		// 开始绘制内1圆
		canvas.drawCircle(mCx, mCy, mInsideRadius * 1, mPaint);

		// 2.开始绘制对角线
		canvas.drawLine(mOutWidth / 2, mCy, mWidth - mOutWidth / 2, mCy, mPaint);// 绘制0°~180°对角线
		canvas.drawLine(mCx, mHeight - mOutWidth / 2, mCx, mOutWidth / 2,
				mPaint);// 绘制90°~270°对角线

		// 根据角度绘制对角线
		int startX, startY, endX, endY;
		double radian;

		// 绘制45°~225°对角线
		// 计算开始位置x/y坐标点
		radian = Math.toRadians((double) 45);// 将角度转换为弧度
		startX = (int) (mCx + mInsideRadius * 4 * Math.cos(radian));// 通过圆心坐标、半径和当前角度计算当前圆周的某点横坐标
		startY = (int) (mCy + mInsideRadius * 4 * Math.sin(radian));// 通过圆心坐标、半径和当前角度计算当前圆周的某点纵坐标
		// 计算结束位置x/y坐标点
		radian = Math.toRadians((double) 45 + 180);
		endX = (int) (mCx + mInsideRadius * 4 * Math.cos(radian));
		endY = (int) (mCy + mInsideRadius * 4 * Math.sin(radian));
		canvas.drawLine(startX, startY, endX, endY, mPaint);

		// 绘制135°~315°对角线
		// 计算开始位置x/y坐标点
		radian = Math.toRadians((double) 135);
		startX = (int) (mCx + mInsideRadius * 4 * Math.cos(radian));
		startY = (int) (mCy + mInsideRadius * 4 * Math.sin(radian));
		// 计算结束位置x/y坐标点
		radian = Math.toRadians((double) 135 + 180);
		endX = (int) (mCx + mInsideRadius * 4 * Math.cos(radian));
		endY = (int) (mCy + mInsideRadius * 4 * Math.sin(radian));
		canvas.drawLine(startX, startY, endX, endY, mPaint);

		// 3.绘制扫描扇形图
		canvas.save();// 用来保存Canvas的状态.save之后,可以调用Canvas的平移、放缩、旋转、错切、裁剪等操作.

		if (isSearching) {// 判断是否处于扫描
			canvas.rotate(mOffsetArgs, mCx, mCy);// 绘制旋转角度,参数一:角度;参数二:x中心;参数三:y中心.
			canvas.drawBitmap(mScanBmp, mCx - mScanBmp.getWidth() / 2, mCy
					- mScanBmp.getHeight() / 2, null);// 绘制Bitmap扫描图片效果
			mOffsetArgs += 3;
		} else {
			canvas.drawBitmap(mScanBmp, mCx - mScanBmp.getWidth() / 2, mCy
					- mScanBmp.getHeight() / 2, null);
		}

		// 4.开始绘制动态点
		canvas.restore();// 用来恢复Canvas之前保存的状态.防止save后对Canvas执行的操作对后续的绘制有影响.

		if (mPointCount > 0) {// 当圆点总数>0时,进入下一层判断

			if (mPointCount > mPointArray.size()) {// 当圆点总数大于存储坐标点数目时,说明有增加,需要重新生成随机坐标点
				int mx = mInsideRadius + mRandom.nextInt(mInsideRadius * 6);
				int my = mInsideRadius + mRandom.nextInt(mInsideRadius * 6);
				mPointArray.add(mx + "/" + my);
			}

			// 开始绘制坐标点
			for (int i = 0; i < mPointArray.size(); i++) {
				String[] result = mPointArray.get(i).split("/");

				// 开始绘制动态点
				if (i < mPointArray.size() - 1)
					canvas.drawBitmap(mDefaultPointBmp,
							Integer.parseInt(result[0]),
							Integer.parseInt(result[1]), null);
				else
					canvas.drawBitmap(mLightPointBmp,
							Integer.parseInt(result[0]),
							Integer.parseInt(result[1]), null);
			}
		}

		if (isSearching)
			this.invalidate();
	}

	/**
	 * TODO<设置扫描状态>
	 * 
	 * @return void
	 */
	public void setSearching(boolean status) {
		this.isSearching = status;
		this.invalidate();
	}

	/**
	 * TODO<新增动态点>
	 * 
	 * @return void
	 */
	public void addPoint() {
		mPointCount++;
		this.invalidate();
	}

	/**
	 * TODO<解析获取控件宽高>
	 * 
	 * @return int
	 */
	private int resolveMeasured(int measureSpec, int desired) {
		int result = 0;
		int specSize = MeasureSpec.getSize(measureSpec);
		switch (MeasureSpec.getMode(measureSpec)) {
		case MeasureSpec.UNSPECIFIED:
			result = desired;
			break;
		case MeasureSpec.AT_MOST:
			result = Math.min(specSize, desired);
			break;
		case MeasureSpec.EXACTLY:
		default:
			result = specSize;
		}
		return result;
	}
}

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/bgp"
    tools:context="com.zihao.radar.MainActivity" >

    <com.zihao.radar.view.RadarView
        android:id="@+id/radar_view"
        android:layout_width="600px"
        android:layout_height="600px"
        android:layout_centerInParent="true" />

</RelativeLayout>



目录
相关文章
|
8月前
|
Android开发
Android中实现获取相册中的图片扫描二维码的功能
Android中实现获取相册中的图片扫描二维码的功能
180 0
|
2天前
|
Shell Android开发 开发者
Android系统 自定义动态修改init.custom.rc
Android系统 自定义动态修改init.custom.rc
19 0
|
2天前
|
测试技术 Android开发 开发者
RK3568 Android系统客制化动态替换ro任意属性
RK3568 Android系统客制化动态替换ro任意属性
14 1
|
2天前
|
存储 Linux Android开发
RK3568 Android/Linux 系统动态更换 U-Boot/Kernel Logo
RK3568 Android/Linux 系统动态更换 U-Boot/Kernel Logo
16 0
|
3天前
|
Android开发
Android RIL 动态切换 4G 模块适配
Android RIL 动态切换 4G 模块适配
6 0
|
3天前
|
Android开发
Android 动态修改参数配置
Android 动态修改参数配置
11 0
|
11天前
|
安全 Android开发 数据安全/隐私保护
Android中的动态权限请求与最佳实践
【4月更文挑战第14天】 在现代安卓应用开发中,用户隐私和安全被赋予了前所未有的重要性。随着Android 6.0(API级别23)引入的运行时权限模型,开发者必须更加细致地处理权限请求,以确保应用功能的完整性同时不侵犯用户的隐私。本文将深入探讨如何在Android应用中实现动态权限请求,分析常见问题,并提供一系列最佳实践,以帮助开发者优雅地处理这一挑战。
21 5
|
6月前
|
SQL 人工智能 移动开发
Android 遍历界面所有的View
本文讲述如何遍历获取页面中所有的view,并输出对应的id,textview文本内容,imageview实际大小及设置的图片大小。 可用于检测android应用中的大图。
|
2月前
|
Android开发 数据安全/隐私保护
【Android Studio】简单的QQ登录界面
【Android Studio】简单的QQ登录界面
|
4月前
|
物联网 Android开发
Android Ble蓝牙App(七)扫描过滤
Android Ble蓝牙App(七)扫描过滤