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>



目录
相关文章
|
29天前
|
缓存 Java Shell
Android 系统缓存扫描与清理方法分析
Android 系统缓存从原理探索到实现。
54 15
Android 系统缓存扫描与清理方法分析
|
1月前
|
XML 数据可视化 Android开发
Android应用界面
Android应用界面中的布局和控件使用,包括相对布局、线性布局、表格布局、帧布局、扁平化布局等,以及AdapterView及其子类如ListView的使用方法和Adapter接口的应用。
25 0
Android应用界面
|
2月前
|
XML Android开发 UED
💥Android UI设计新风尚!掌握Material Design精髓,让你的界面颜值爆表!🎨
随着移动应用市场的蓬勃发展,用户对界面设计的要求日益提高。为此,掌握由Google推出的Material Design设计语言成为提升应用颜值和用户体验的关键。本文将带你深入了解Material Design的核心原则,如真实感、统一性和创新性,并通过丰富的组件库及示例代码,助你轻松打造美观且一致的应用界面。无论是色彩搭配还是动画效果,Material Design都能为你的Android应用增添无限魅力。
69 1
|
6月前
|
Android开发
定制Android关机界面
定制Android关机界面
96 0
|
3月前
|
Android开发 iOS开发 C#
Xamarin.Forms:从零开始的快速入门指南——打造你的首个跨平台移动应用,轻松学会用C#和XAML构建iOS与Android通用界面的每一个步骤
【8月更文挑战第31天】Xamarin.Forms 是一个强大的框架,让开发者通过单一共享代码库构建跨平台移动应用,支持 iOS、Android 和 Windows。使用 C# 和 XAML,它简化了多平台开发流程并保持一致的用户体验。本指南通过创建一个简单的 “HelloXamarin” 应用演示了 Xamarin.Forms 的基本功能和工作原理。
90 0
|
4月前
|
XML Android开发 UED
💥Android UI设计新风尚!掌握Material Design精髓,让你的界面颜值爆表!🎨
【7月更文挑战第28天】随着移动应用市场的发展,用户对界面设计的要求不断提高。Material Design是由Google推出的设计语言,强调真实感、统一性和创新性,通过模拟纸张和墨水的物理属性创造沉浸式体验。它注重色彩、排版、图标和布局的一致性,确保跨设备的统一视觉风格。Android Studio提供了丰富的Material Design组件库,如按钮、卡片等,易于使用且美观。
154 1
|
4月前
|
XML Android开发 数据安全/隐私保护
使用RelativeLayout布局Android界面
使用RelativeLayout布局Android界面
|
5月前
|
Android开发
Android中如何动态的调整Dialog的背景深暗
在Android开发中,Dialog和DialogFragment可通过设置`Window`的`backgroundDimAmount`来控制背景变暗,突出对话框。在DialogFragment的`onCreateDialog`或`onViewCreated`中,获取`Dialog`的`Window`,设置`LayoutParams.dimAmount`(例如0.5f)并添加`FLAG_DIM_BEHIND`标志。要动态调整,可保存`LayoutParams`并在需要时更新。对于Dialog,创建时直接设置同样属性。还可以通过定义主题样式设置背景模糊程度。
151 7
|
5月前
|
编解码 安全 Android开发
探索iOS与Android开发的差异:从界面到性能
【6月更文挑战第10天】在移动应用开发的广阔天地中,iOS和Android两大平台各占山头,它们在设计理念、用户体验、性能优化等方面展现出独特的魅力。本文将深入探讨这两大系统在开发过程中的主要差异,从用户界面设计到性能调优,揭示各自背后的技术逻辑与创新策略,为开发者提供全面的视角和实用的开发指南。
|
5月前
|
XML Android开发 数据格式
【Android UI】使用RelativeLayout与TableLayout实现登录界面
【Android UI】使用RelativeLayout与TableLayout实现登录界面
52 5
下一篇
无影云桌面