您好,登錄后才能下訂單哦!
這篇文章主要講解了“Android自定義View實現地鐵顯示牌的效果”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“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); }}
感謝各位的閱讀,以上就是“Android自定義View實現地鐵顯示牌的效果”的內容了,經過本文的學習后,相信大家對Android自定義View實現地鐵顯示牌的效果這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。