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

Android自定义View实现地铁显示牌效果

程序员文章站 2023-10-31 08:25:52
本文实例为大家分享了android地铁显示牌的具体代码,供大家参考,具体内容如下 预览效果 目录 subwayboardview.java 代码 public c...

本文实例为大家分享了android地铁显示牌的具体代码,供大家参考,具体内容如下

预览效果

Android自定义View实现地铁显示牌效果

目录

subwayboardview.java

代码

public class subwayboardview extends view {

 private paint bgpaint, tbpaint, centerbgpaint, centerringpaint, centercirclepaint, centercircleringpaint, nostationpaint, stationpaint, doorpaint;

 private textpaint centertextpaint, stationtextpaint, currentstationtextpaint, doortextpaint;

 private float barheight = densityutil.dp2px(getcontext(), 20);

 private float centercirclewidth;
 private float centerringwidth;
 private float centercircleringstrokewidth = densityutil.dp2px(getcontext(), 5);
 private float centerringstrokewidth = densityutil.dp2px(getcontext(), 36);

 private float centercircleringsweepangle = 0f;
 private objectanimator centercircleringanim;

 private list<string> nostationstrs = new arraylist<>();
 private list<string> stationstrs = new arraylist<>();
 private string currentstationstrs = "杭州站";
 private bitmap doorbitmap;
 private camera camera;

 public subwayboardview(context context) {
  super(context);
  initview();
 }

 public subwayboardview(context context, @nullable attributeset attrs) {
  super(context, attrs);
  initview();
 }

 public subwayboardview(context context, @nullable attributeset attrs, int defstyleattr) {
  super(context, attrs, defstyleattr);
  initview();
 }

 private void initview() {
  //全背景
  bgpaint = new paint(paint.anti_alias_flag);
  bgpaint.setstyle(paint.style.fill);
  bgpaint.setcolor(color.parsecolor("#85919a"));

  //上下边栏
  tbpaint = new paint(paint.anti_alias_flag);
  tbpaint.setstyle(paint.style.fill);
  tbpaint.setcolor(color.parsecolor("#c21b2c"));

  //中间栏
  centerbgpaint = new paint(paint.anti_alias_flag);
  centerbgpaint.setstyle(paint.style.fill);
  centerbgpaint.setcolor(color.parsecolor("#92a3d1"));

  //中间空白圆环区域
  centerringpaint = new paint(paint.anti_alias_flag);
  centerringpaint.setstyle(paint.style.stroke);
  centerringpaint.setstrokewidth(centerringstrokewidth);
  centerringpaint.setcolor(color.parsecolor("#85919a"));

  //中间圆
  centercirclepaint = new paint(paint.anti_alias_flag);
  centercirclepaint.setstyle(paint.style.fill);
  centercirclepaint.setcolor(color.parsecolor("#c21b2c"));

  //中间圆边上的圆环
  centercircleringpaint = new paint(paint.anti_alias_flag);
  centercircleringpaint.setstyle(paint.style.stroke);
  centercircleringpaint.setstrokewidth(centercircleringstrokewidth);
  centercircleringpaint.setstrokecap(paint.cap.round);
  centercircleringpaint.setcolor(color.parsecolor("#6e8ca6"));

  //中间文字
  centertextpaint = new textpaint(paint.anti_alias_flag);
  centertextpaint.setstyle(paint.style.fill);
  centertextpaint.setfakeboldtext(true);
  centertextpaint.setcolor(color.parsecolor("#333333"));
  centertextpaint.settextalign(paint.align.center);
  centertextpaint.setshadowlayer(3, 3, 3, color.parsecolor("#6e8ca6"));
  centertextpaint.settextsize(densityutil.sp2px(getcontext(), 24));

  //未到达的站
  nostationpaint = new paint(paint.anti_alias_flag);
  nostationpaint.setstyle(paint.style.fill_and_stroke);
  nostationpaint.setcolor(color.parsecolor("#c21b2c"));

  //未到站文字
  stationtextpaint = new textpaint(paint.anti_alias_flag);
  stationtextpaint.setstyle(paint.style.fill);
  stationtextpaint.setcolor(color.parsecolor("#333333"));
  stationtextpaint.settextalign(paint.align.center);
  stationtextpaint.setshadowlayer(3, 3, 3, color.parsecolor("#6e8ca6"));
  stationtextpaint.settextsize(densityutil.sp2px(getcontext(), 18));

  nostationstrs.add("宁波站");
  nostationstrs.add("上虞站");
  nostationstrs.add("绍兴站");

  //已到达的站
  stationpaint = new paint(paint.anti_alias_flag);
  stationpaint.setstyle(paint.style.fill_and_stroke);
  stationpaint.setcolor(color.parsecolor("#7586b2"));

  stationstrs.add("南京站");
  stationstrs.add("苏州站");
  stationstrs.add("上海站");

  //到站文字
  currentstationtextpaint = new textpaint(paint.anti_alias_flag);
  currentstationtextpaint.setstyle(paint.style.fill);
  currentstationtextpaint.setfakeboldtext(true);
  currentstationtextpaint.setcolor(color.parsecolor("#3d5d9a"));
  currentstationtextpaint.settextalign(paint.align.left);
  currentstationtextpaint.settextsize(densityutil.sp2px(getcontext(), 18));

  doorpaint = new paint(paint.anti_alias_flag);
  doorbitmap = bitmapfactory.decoderesource(getresources(), r.mipmap.open_door);

  doortextpaint = new textpaint(paint.anti_alias_flag);
  doortextpaint.setstyle(paint.style.fill);
  doortextpaint.setcolor(color.parsecolor("#c21b2c"));
  doortextpaint.settextalign(paint.align.left);
  doortextpaint.settextsize(densityutil.sp2px(getcontext(), 14));

  camera = new camera();
 }

 @override
 protected void ondraw(canvas canvas) {
  super.ondraw(canvas);
  int width = getwidth();
  int height = getheight();

  int centerx = width / 2;
  int centery = height / 2;

  //计算中间空白圆形宽度
  if (0 == centerringwidth) {
   centerringwidth = (height - densityutil.dp2px(getcontext(), 12)) * 1f / 2;
  }
  //计算中间圆的半径
  if (0 == centercirclewidth) {
   centercirclewidth = centerringwidth - densityutil.dp2px(getcontext(), 8);
  }

  //背景
  canvas.drawrect(0, 0, width, height, bgpaint);

  //上下栏
  canvas.drawrect(0, 0, width, barheight, tbpaint);
  canvas.drawrect(0, height - barheight, width, height, tbpaint);

  //中间圆环空白区域
  canvas.drawcircle(centerx, centery, centerringwidth, centerringpaint);

  //中间栏
  float centerlinet = barheight + densityutil.dp2px(getcontext(), 10);
  float centerlineb = height - barheight - densityutil.dp2px(getcontext(), 10);
  canvas.drawrect(0, centerlinet, width, centerlineb, centerbgpaint);

  //中间圆
  canvas.drawcircle(centerx, centery, centercirclewidth, centercirclepaint);

  //中间圆环
  if (centercircleringsweepangle > 0) {
   canvas.drawarc(centerx - centercirclewidth - (centercircleringstrokewidth / 2), centery - centercirclewidth - (centercircleringstrokewidth / 2), centerx + centercirclewidth + (centercircleringstrokewidth / 2), centery + centercirclewidth + (centercircleringstrokewidth / 2), -90f, centercircleringsweepangle, false, centercircleringpaint);
  }

  //中间文字
  paint.fontmetrics fontmetrics = centertextpaint.getfontmetrics();
  float dx = (fontmetrics.bottom - fontmetrics.top) / 2 - fontmetrics.bottom;
  canvas.drawtext(currentstationstrs, centerx, centery + dx, centertextpaint);

  //未到站
  float stationstart = densityutil.dp2px(getcontext(), 20);
  float stationwidth = densityutil.dp2px(getcontext(), 40);
  float stationpadding = densityutil.dp2px(getcontext(), 20);
  for (int i = 0; i < nostationstrs.size(); i++) {
   canvas.drawpath(getstationview(stationstart + (stationwidth + stationpadding) * i, stationwidth, centerlinet, centerlineb), nostationpaint);

   //保存画布
   canvas.save();
   string stationstr = nostationstrs.get(i);
   paint.fontmetrics fm = stationtextpaint.getfontmetrics();
   //文字高度
   float fontheight = (fm.bottom - fm.top) * stationstr.length();
   //显示高度
   float showheigth = centerlineb - centerlinet;
   //移动画布
   canvas.translate(stationstart + (stationwidth + stationpadding) * i + stationwidth / 3, centerlinet + (showheigth - fontheight) / 2);
   float strwidth = stationtextpaint.measuretext(stationstr) / stationstr.length();
   staticlayout staticlayout;
   if (build.version.sdk_int >= build.version_codes.m) {
    staticlayout = staticlayout.builder.obtain(stationstr, 0, stationstr.length(), stationtextpaint, (int) strwidth).build();
   } else {
    staticlayout = new staticlayout(stationstr, stationtextpaint, (int) strwidth, layout.alignment.align_center, 1, 0, true);
   }
   //绘制
   staticlayout.draw(canvas);
   //还原画布
   canvas.translate(-stationstart + (stationwidth + stationpadding) * i, -centerlinet);
   canvas.restore();
  }

  //已过站
  float stationend = getwidth() - densityutil.dp2px(getcontext(), 20) - stationwidth;
  for (int i = 0; i < stationstrs.size(); i++) {
   canvas.drawpath(getstationview(stationend - (stationwidth + stationpadding) * i, stationwidth, centerlinet, centerlineb), stationpaint);

   //保存画布
   canvas.save();
   string stationstr = nostationstrs.get(i);
   paint.fontmetrics fm = stationtextpaint.getfontmetrics();
   //文字高度
   float fontheight = (fm.bottom - fm.top) * stationstr.length();
   //显示高度
   float showheigth = centerlineb - centerlinet;
   //移动画布
   canvas.translate(stationend - (stationwidth + stationpadding) * i + stationwidth / 3, centerlinet + (showheigth - fontheight) / 2);
   float strwidth = stationtextpaint.measuretext(stationstr) / stationstr.length();
   staticlayout staticlayout;
   if (build.version.sdk_int >= build.version_codes.m) {
    staticlayout = staticlayout.builder.obtain(stationstr, 0, stationstr.length(), stationtextpaint, (int) strwidth).build();
   } else {
    staticlayout = new staticlayout(stationstr, stationtextpaint, (int) strwidth, layout.alignment.align_center, 1, 0, true);
   }
   //绘制
   staticlayout.draw(canvas);
   //还原画布
   canvas.translate(-stationstart + (stationwidth + stationpadding) * i, -centerlinet);
   canvas.restore();
  }

  //到达站
  string curentstr = "停靠站" + currentstationstrs;
  float fontwidth = stationtextpaint.measuretext(curentstr) / curentstr.length();
  float pointx = centerx - centerringwidth - fontwidth * 3 - densityutil.dp2px(getcontext(), 26);
  paint.fontmetrics fm = stationtextpaint.getfontmetrics();
  float pointy = centerlinet + ((centerlineb - centerlinet) - (fm.bottom - fm.top) * 2) / 2;
  canvas.save();
  canvas.translate(pointx, pointy);
  staticlayout staticlayout;
  if (build.version.sdk_int >= build.version_codes.m) {
   staticlayout = staticlayout.builder.obtain(curentstr, 0, curentstr.length(), stationtextpaint, (int) (fontwidth * 3)).build();
  } else {
   staticlayout = new staticlayout(curentstr, stationtextpaint, (int) (fontwidth * 3), layout.alignment.align_center, 1, 0, true);
  }
  //绘制
  staticlayout.draw(canvas);
  canvas.translate(-pointx, -centerlinet);
  canvas.restore();

  //开门提示
  string primt = "注意开门";
  float doortextwidth = doortextpaint.measuretext(primt);
  paint.fontmetrics doortextfm = doortextpaint.getfontmetrics();
  float doortextheight = doortextfm.bottom - doortextfm.top;
  float dy = doortextheight / 2 - doortextfm.bottom;
  int doortextleft = (int) (centerx + centerringwidth + densityutil.dp2px(getcontext(), 26));
  rect rect = new rect();
  rect.left = (int) (doortextleft + ((doortextwidth - doorbitmap.getwidth()) / 2));
  rect.top = (int) (centerlinet + ((centerlineb - centerlinet) - (doorbitmap.getheight() + densityutil.dp2px(getcontext(), 6) + + doortextheight)) / 2);
  rect.right = rect.left + doorbitmap.getwidth();
  rect.bottom = rect.top + doorbitmap.getheight();
  //旋转
  canvas.save();
  camera.save();
  canvas.translate(rect.left, rect.top);
  camera.rotatey(-45);
  camera.applytocanvas(canvas);
  canvas.translate(-rect.left, -rect.top);
  camera.restore();
  canvas.drawbitmap(doorbitmap, null, rect, doorpaint);
  canvas.restore();
  canvas.drawtext(primt, doortextleft, rect.bottom + densityutil.dp2px(getcontext(), 6) + (doortextheight / 2) + dy, doortextpaint);
 }

 /**
  * 获取站信息
  *
  * @param pl
  * @param width
  * @param centerlinet
  * @param centerlineb
  * @return
  */
 private path getstationview(float pl, float width, float centerlinet, float centerlineb) {
  float pt = centerlinet;
  float pr = pl + width;
  float pb = centerlineb;
  float r = (pr - pl) / 3;
  path path = new path();
  path.moveto(pl, pt);
  path.lineto(pr, pt);
  path.quadto(pr - r, pt + (pb - pt) / 2, pr, pb);
  path.lineto(pl, pb);
  path.quadto(pl - r, pt + (pb - pt) / 2, pl, pt);
  path.close();
  return path;
 }

 public void setcentercircleringsweepangle(float centercircleringsweepangle) {
  this.centercircleringsweepangle = centercircleringsweepangle;
  invalidate();
 }

 /**
  * 开始中间圆动画
  */
 public void animcentercirclering() {
  if (null == centercircleringanim) {
   centercircleringanim = objectanimator.offloat(this, "centercircleringsweepangle", 0f, 360f);
   centercircleringanim.setduration(3000);
   centercircleringanim.setinterpolator(new linearinterpolator());
   centercircleringanim.setrepeatcount(valueanimator.infinite);
   centercircleringanim.setrepeatmode(valueanimator.restart);
  }
  centercircleringanim.start();
 }

 /**
  * 停止
  */
 public void stopanimcentercirclering() {
  if (null != centercircleringanim) {
   centercircleringanim.cancel();
  }
  setcentercircleringsweepangle(0);
 }
}

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