中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么在Android中自定義View實現地鐵顯示牌效果

發布時間:2021-05-27 17:48:17 來源:億速云 閱讀:173 作者: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

九龙县| 湖南省| 囊谦县| 星子县| 鹿邑县| 枞阳县| 平顺县| 石嘴山市| 老河口市| 天长市| 饶河县| 磴口县| 克拉玛依市| 师宗县| 顺昌县| 峨眉山市| 勃利县| 县级市| 元阳县| 寿阳县| 察雅县| 无极县| 平乡县| 桦南县| 五原县| 宣城市| 海宁市| 依安县| 富裕县| 屏东县| 改则县| 兴山县| 和顺县| 锦屏县| 南昌县| 大港区| 那坡县| 青岛市| 连山| 平顶山市| 武义县|