温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

怎么在Android中自定义View实现地铁显示牌效果

发布时间:2021-05-27 17:48:17 来源:亿速云 阅读:224 作者:Leah 栏目:移动开发

这篇文章将为大家详细讲解有关怎么在Android中自定义View实现地铁显示牌效果,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。

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);  } }

关于怎么在Android中自定义View实现地铁显示牌效果就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI