欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

基于Android自定义控件实现雷达效果

程序员文章站 2024-02-06 20:13:28
如何制作出类似雷达扫描的效果,具体方法如下 一、效果图 二、实现思路 1、自定义控件radarview用来画雷达的效果图,可以自定义属性包括 bac...

如何制作出类似雷达扫描的效果,具体方法如下

一、效果图

基于Android自定义控件实现雷达效果

二、实现思路

1、自定义控件radarview用来画雷达的效果图,可以自定义属性包括

backgroundcolor:背景颜色
circlenum:圆的数量
startcolor:开始颜色
endcolor:结束颜色
linecolor:线的颜色

2、通过handler循环发送消息到messagequeue中,将mrotate加3,使matrix旋转mrotate,重绘雷达扫描的圆。

3、通过梯度渐变扫描渲染器sweepgradient,在绘制圆的过程中,将颜色从startcolor变为endcolor。

三、实例代码

public class radarview extends view {
 private final string tag = "radarview";

 private static final int msg_what = 1;

 private static final int delay_time = 20;

 //设置默认宽高,雷达一般都是圆形,所以我们下面取宽高会取math.min(宽,高)
 private final int default_width = 200;

 private final int default_height = 200;
 //雷达的半径
 private int mradarradius;
 //雷达画笔
 private paint mradarpaint;
 //雷达底色画笔
 private paint mradarbg;
 //雷达圆圈的个数,默认4个
 private int mcirclenum = 4;
 //雷达线条的颜色,默认为白色
 private int mcirclecolor = color.white;
 //雷达圆圈背景色
 private int mradarbgcolor = color.black;
 //paintshader
 private shader mradarshader;

 //雷达扫描时候的起始和终止颜色
 private int mstartcolor = 0x0000ff00;

 private int mendcolor = 0xaa00ff00;


 private matrix mmatrix;

 //旋转的角度
 private int mrotate = 0;

 private handler mhandler = new handler() {
  @override
  public void handlemessage(message msg) {
   super.handlemessage(msg);

   mrotate += 3;
   postinvalidate();

   mmatrix.reset();
   mmatrix.prerotate(mrotate, 0, 0);
   //延时delay_time后再发送消息
   mhandler.sendemptymessagedelayed(msg_what, delay_time);
  }
 };

 public radarview(context context) {
  this(context, null);
 }

 public radarview(context context, attributeset attrs) {
  this(context, attrs, 0);
 }

 public radarview(context context, attributeset attrs, int defstyleattr) {
  super(context, attrs, defstyleattr);
  init(context, attrs);

  //设置抗锯齿
  mradarbg = new paint(paint.anti_alias_flag);
  //画笔颜色
  mradarbg.setcolor(mradarbgcolor);
  //画实心圆
  mradarbg.setstyle(paint.style.fill);

  //设置抗锯齿
  mradarpaint = new paint(paint.anti_alias_flag);
  //画笔颜色
  mradarpaint.setcolor(mcirclecolor);
  //设置空心的画笔,只画圆边
  mradarpaint.setstyle(paint.style.stroke);
  //画笔宽度
  mradarpaint.setstrokewidth(2);
  //使用梯度渐变渲染器,
  mradarshader = new sweepgradient(0, 0, mstartcolor, mendcolor);

  mmatrix = new matrix();
 }


 //初始化,拓展可设置参数供布局使用
 private void init(context context, attributeset attrs) {
  if (attrs != null) {
   typedarray ta = context.obtainstyledattributes(attrs, r.styleable.radarview);
   mstartcolor = ta.getcolor(r.styleable.radarview_startcolor, mstartcolor);
   mendcolor = ta.getcolor(r.styleable.radarview_endcolor, mendcolor);
   mradarbgcolor = ta.getcolor(r.styleable.radarview_backgroundcolor, mradarbgcolor);
   mcirclecolor = ta.getcolor(r.styleable.radarview_linecolor, mcirclecolor);
   mcirclenum = ta.getinteger(r.styleable.radarview_circlenum, mcirclenum);
   ta.recycle();
  }
 }


 @override
 protected void onsizechanged(int w, int h, int oldw, int oldh) {
  super.onsizechanged(w, h, oldw, oldh);
  //雷达的半径为宽的一半或高的一半的最小值
  mradarradius = math.min(w / 2, h / 2);
 }

 @override
 protected void onmeasure(int widthmeasurespec, int heightmeasurespec) {
  super.onmeasure(widthmeasurespec, heightmeasurespec);
  //获取宽度
  int width = measuresize(1, default_width, widthmeasurespec);
  //获取高度
  int height = measuresize(0, default_height, heightmeasurespec);

  //取最大的 宽|高
  int measuresize = math.max(width, height);
  setmeasureddimension(measuresize, measuresize);
 }


 /**
  * 测绘measure
  *
  * @param spectype 1为宽, 其他为高
  * @param contentsize 默认值
  */
 private int measuresize(int spectype, int contentsize, int measurespec) {
  int result;
  //获取测量的模式和size
  int specmode = measurespec.getmode(measurespec);
  int specsize = measurespec.getsize(measurespec);

  if (specmode == measurespec.exactly) {
   result = math.max(contentsize, specsize);
  } else {
   result = contentsize;

   if (spectype == 1) {
    // 根据传入方式计算宽
    result += (getpaddingleft() + getpaddingright());
   } else {
    // 根据传入方式计算高
    result += (getpaddingtop() + getpaddingbottom());
   }
  }

  return result;

 }


 @override
 protected void ondraw(canvas canvas) {
  super.ondraw(canvas);

  log.d(tag, "ondraw " + mrotate);

  mradarbg.setshader(null);

  //将画布移动到屏幕的中心点
  canvas.translate(mradarradius, mradarradius);
  //绘制底色,让雷达的线看起来更清晰
  canvas.drawcircle(0, 0, mradarradius, mradarbg);
  //画圆圈
  for (int i = 1; i <= mcirclenum; i++) {
   canvas.drawcircle(0, 0, (float) (i * 1.0 / mcirclenum * mradarradius), mradarpaint);
  }
  //绘制雷达基线 x轴
  canvas.drawline(-mradarradius, 0, mradarradius, 0, mradarpaint);
  //绘制雷达基线 y轴
  canvas.drawline(0, mradarradius, 0, -mradarradius, mradarpaint);
  //设置颜色渐变从透明到不透明
  mradarbg.setshader(mradarshader);
  //设置矩阵
  canvas.concat(mmatrix);
  canvas.drawcircle(0, 0, mradarradius, mradarbg);
 }


 public void startscan() {
  mhandler.removemessages(msg_what);
  mhandler.sendemptymessage(msg_what);
 }

 public void stopscan() {
  mhandler.removemessages(msg_what);
 }
}

布局文件:

<relativelayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:app="http://schemas.android.com/apk/res-auto"
 xmlns:tools="http://schemas.android.com/tools"
 android:id="@+id/activity_main"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 >
 <com.android.demo.ui.shader.radarview
  android:id="@+id/radarview"
  android:layout_width="300dp"
  android:layout_height="300dp"
  android:layout_centerinparent="true"
  app:backgroundcolor="#000000"
  app:circlenum="4"
  app:endcolor="#aaff0000"
  app:linecolor="#00ff00"
  app:startcolor="#aa0000ff"/>

 <button
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_alignparentleft="true"
  android:layout_alignparentbottom="true"
  android:onclick="start"
  android:text="开始" />

 <button
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_alignparentright="true"
  android:layout_alignparentbottom="true"
  android:onclick="stop"
  android:text="停止" />
</relativelayout>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。