国产成人精品久久免费动漫-国产成人精品天堂-国产成人精品区在线观看-国产成人精品日本-a级毛片无码免费真人-a级毛片毛片免费观看久潮喷

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

Android實(shí)現(xiàn)儀表盤(pán)效果

瀏覽:86日期:2022-09-18 13:38:16

本文實(shí)例為大家分享了Android實(shí)現(xiàn)儀表盤(pán)效果的具體代碼,供大家參考,具體內(nèi)容如下

儀表盤(pán)效果,圓弧可變色,效果圖如下:

Android實(shí)現(xiàn)儀表盤(pán)效果

通過(guò)自定義view實(shí)現(xiàn),代碼如下:

public class DashboardView extends View { private int mRadius; // 畫(huà)布邊緣半徑(去除padding后的半徑) private int mStartAngle = 150; // 起始角度 private int mSweepAngle = 240; // 繪制角度 private int mMin = 1; // 最小值 private int mMax = 8; // 最大值 private int mSection = 8; // 值域(mMax-mMin)等分份數(shù) private int mPortion = 3; // 一個(gè)mSection等分份數(shù) private String mHeaderText = ''; // 表頭 private int mCreditValue = (int) 8.12; // 信用分 private int mSolidCreditValue = mCreditValue; // 信用分(設(shè)定后不變) private int mSparkleWidth; // 亮點(diǎn)寬度 private int mProgressWidth; // 進(jìn)度圓弧寬度 private float mLength1; // 刻度頂部相對(duì)邊緣的長(zhǎng)度 private int mCalibrationWidth; // 刻度圓弧寬度 private float mLength2; // 刻度讀數(shù)頂部相對(duì)邊緣的長(zhǎng)度 private int mPadding; private float mCenterX, mCenterY; // 圓心坐標(biāo) private Paint mPaint; private RectF mRectFProgressArc; private RectF mRectFCalibrationFArc; private RectF mRectFTextArc; private Path mPath; private Rect mRectText; private String[] mTexts; private int mBackgroundColor; private int[] mBgColors; private boolean isAnimFinish = true; private float mAngleWhenAnim; public DashboardView(Context context) {this(context, null); } public DashboardView(Context context, AttributeSet attrs) {this(context, attrs, 0); } public DashboardView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init(); } private void init() {mSparkleWidth = dp2px(10);mProgressWidth = dp2px(3);mCalibrationWidth = dp2px(10);mPaint = new Paint();mPaint.setAntiAlias(true);mPaint.setStrokeCap(Paint.Cap.ROUND);mRectFProgressArc = new RectF();mRectFCalibrationFArc = new RectF();mRectFTextArc = new RectF();mPath = new Path();mRectText = new Rect();mTexts = new String[]{'', 'Ⅳ', '', 'Ⅲ', '', 'Ⅱ', '', 'Ⅰ', ''};mBgColors = new int[]{ContextCompat.getColor(getContext(), R.color.color_red),ContextCompat.getColor(getContext(), R.color.color_orange),ContextCompat.getColor(getContext(), R.color.color_yellow),ContextCompat.getColor(getContext(), R.color.color_green),ContextCompat.getColor(getContext(), R.color.color_blue)};mBackgroundColor = mBgColors[0]; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);mPadding = Math.max(Math.max(getPaddingLeft(), getPaddingTop()),Math.max(getPaddingRight(), getPaddingBottom()));setPadding(mPadding, mPadding, mPadding, mPadding);mLength1 = mPadding + mSparkleWidth / 2f + dp2px(8);mLength2 = mLength1 + mCalibrationWidth + dp2px(1) + dp2px(5);int width = resolveSize(dp2px(220), widthMeasureSpec);mRadius = (width - mPadding * 2) / 2;setMeasuredDimension(width, width - dp2px(30));mCenterX = mCenterY = getMeasuredWidth() / 2f;mRectFProgressArc.set(mPadding + mSparkleWidth / 2f,mPadding + mSparkleWidth / 2f,getMeasuredWidth() - mPadding - mSparkleWidth / 2f,getMeasuredWidth() - mPadding - mSparkleWidth / 2f);mRectFCalibrationFArc.set(mLength1 + mCalibrationWidth / 2f,mLength1 + mCalibrationWidth / 2f,getMeasuredWidth() - mLength1 - mCalibrationWidth / 2f,getMeasuredWidth() - mLength1 - mCalibrationWidth / 2f);mPaint.setTextSize(sp2px(10));mPaint.getTextBounds('0', 0, '0'.length(), mRectText);mRectFTextArc.set(mLength2 + mRectText.height(),mLength2 + mRectText.height(),getMeasuredWidth() - mLength2 - mRectText.height(),getMeasuredWidth() - mLength2 - mRectText.height()); } @SuppressLint('ResourceAsColor') @Override protected void onDraw(Canvas canvas) {super.onDraw(canvas);//canvas.drawColor(mBackgroundColor);//canvas.drawColor(R.color.color_blue);/** * 畫(huà)進(jìn)度圓弧背景 */mPaint.setStrokeCap(Paint.Cap.ROUND);mPaint.setStyle(Paint.Style.STROKE);mPaint.setStrokeWidth(mProgressWidth);mPaint.setAlpha(80);mPaint.setColor(mBackgroundColor);canvas.drawArc(mRectFProgressArc, mStartAngle + 1, mSweepAngle - 2, false, mPaint);mPaint.setAlpha(255);if (isAnimFinish) { /** * 畫(huà)進(jìn)度圓弧(起始到信用值) */ mPaint.setShader(generateSweepGradient()); mPaint.setColor(mBackgroundColor); canvas.drawArc(mRectFProgressArc, mStartAngle + 1, calculateRelativeAngleWithValue(mCreditValue) - 2, false, mPaint); /** * 畫(huà)指示亮點(diǎn) */ float[] point = getCoordinatePoint( mRadius - mSparkleWidth / 2f, mStartAngle + calculateRelativeAngleWithValue(mCreditValue) ); mPaint.setStyle(Paint.Style.FILL); mPaint.setShader(generateRadialGradient(point[0], point[1])); mPaint.setColor(mBackgroundColor); canvas.drawCircle(point[0], point[1], mSparkleWidth / 2f, mPaint);} else { /** * 畫(huà)進(jìn)度圓弧(起始到信用值) */ mPaint.setShader(generateSweepGradient()); mPaint.setColor(mBackgroundColor); canvas.drawArc(mRectFProgressArc, mStartAngle + 1, mAngleWhenAnim - mStartAngle - 2, false, mPaint); /** * 畫(huà)指示亮點(diǎn) */ float[] point = getCoordinatePoint( mRadius - mSparkleWidth / 2f, mAngleWhenAnim ); mPaint.setStyle(Paint.Style.FILL); mPaint.setColor(mBackgroundColor); mPaint.setShader(generateRadialGradient(point[0], point[1])); canvas.drawCircle(point[0], point[1], mSparkleWidth / 2f, mPaint);}/** * 畫(huà)刻度圓弧 */mPaint.setShader(null);mPaint.setStyle(Paint.Style.STROKE);mPaint.setColor(Color.WHITE);mPaint.setAlpha(80);mPaint.setStrokeCap(Paint.Cap.SQUARE);mPaint.setStrokeWidth(mCalibrationWidth);mPaint.setColor(mBackgroundColor);canvas.drawArc(mRectFCalibrationFArc, mStartAngle + 3, mSweepAngle - 6, false, mPaint);/** * 畫(huà)長(zhǎng)刻度 * 畫(huà)好起始角度的一條刻度后通過(guò)canvas繞著原點(diǎn)旋轉(zhuǎn)來(lái)畫(huà)剩下的長(zhǎng)刻度 */mPaint.setStrokeCap(Paint.Cap.ROUND);mPaint.setStrokeWidth(dp2px(2));mPaint.setAlpha(120);mPaint.setColor(mBackgroundColor);float x0 = mCenterX;float y0 = mPadding + mLength1 + dp2px(1);float x1 = mCenterX;float y1 = y0 + mCalibrationWidth;// 逆時(shí)針到開(kāi)始處canvas.save();canvas.drawLine(x0, y0, x1, y1, mPaint);float degree = mSweepAngle / mSection;for (int i = 0; i < mSection / 2; i++) { canvas.rotate(-degree, mCenterX, mCenterY); canvas.drawLine(x0, y0, x1, y1, mPaint);}canvas.restore();// 順時(shí)針到結(jié)尾處canvas.save();for (int i = 0; i < mSection / 2; i++) { canvas.rotate(degree, mCenterX, mCenterY); canvas.drawLine(x0, y0, x1, y1, mPaint);}canvas.restore();/** * 畫(huà)短刻度 * 同樣采用canvas的旋轉(zhuǎn)原理 */mPaint.setStrokeWidth(dp2px(1));mPaint.setAlpha(80);mPaint.setColor(mBackgroundColor);float x2 = mCenterX;float y2 = y0 + mCalibrationWidth - dp2px(2);// 逆時(shí)針到開(kāi)始處canvas.save();canvas.drawLine(x0, y0, x2, y2, mPaint);degree = mSweepAngle / (mSection * mPortion);for (int i = 0; i < (mSection * mPortion) / 2; i++) { canvas.rotate(-degree, mCenterX, mCenterY); canvas.drawLine(x0, y0, x2, y2, mPaint);}canvas.restore();// 順時(shí)針到結(jié)尾處canvas.save();for (int i = 0; i < (mSection * mPortion) / 2; i++) { canvas.rotate(degree, mCenterX, mCenterY); canvas.drawLine(x0, y0, x2, y2, mPaint);}canvas.restore();/** * 畫(huà)長(zhǎng)刻度讀數(shù) * 添加一個(gè)圓弧path,文字沿著path繪制 */mPaint.setTextSize(sp2px(10));mPaint.setTextAlign(Paint.Align.LEFT);mPaint.setStyle(Paint.Style.FILL);mPaint.setAlpha(160);mPaint.setColor(mBackgroundColor);for (int i = 0; i < mTexts.length; i++) { mPaint.getTextBounds(mTexts[i], 0, mTexts[i].length(), mRectText); // 粗略把文字的寬度視為圓心角2*θ對(duì)應(yīng)的弧長(zhǎng),利用弧長(zhǎng)公式得到θ,下面用于修正角度 float θ = (float) (180 * mRectText.width() / 2 / (Math.PI * (mRadius - mLength2 - mRectText.height()))); mPath.reset(); mPath.addArc( mRectFTextArc, mStartAngle + i * (mSweepAngle / mSection) - θ, // 正起始角度減去θ使文字居中對(duì)準(zhǔn)長(zhǎng)刻度 mSweepAngle ); canvas.drawTextOnPath(mTexts[i], mPath, 0, 0, mPaint);}/** * 畫(huà)實(shí)時(shí)度數(shù)值 */mPaint.setAlpha(255);mPaint.setTextSize(sp2px(50));mPaint.setTextAlign(Paint.Align.CENTER);mPaint.setColor(mBackgroundColor);//String value = String.valueOf(mSolidCreditValue);String value = '';if (mSolidCreditValue > 6) { //'Ⅳ', '', 'Ⅲ', '', 'Ⅱ', '', 'Ⅰ', value = 'Ⅰ';} else if (5 < mSolidCreditValue && mSolidCreditValue <= 6) { value = 'Ⅱ';} else if (4 < mSolidCreditValue && mSolidCreditValue <= 5) { value = 'Ⅲ';} else if (3 < mSolidCreditValue && mSolidCreditValue <= 4) { value = 'Ⅳ';}canvas.drawText(value, mCenterX, mCenterY + dp2px(30), mPaint);/** * 畫(huà)表頭 */mPaint.setAlpha(160);mPaint.setTextSize(sp2px(12));mPaint.setColor(Color.BLACK);canvas.drawText(mHeaderText, mCenterX, mCenterY - dp2px(20), mPaint);/** * 畫(huà)描述 */mPaint.setAlpha(255);mPaint.setTextSize(sp2px(20));mPaint.setColor(mBackgroundColor);canvas.drawText(calculateCreditDescription(), mCenterX, mCenterY + dp2px(55), mPaint);/** * 畫(huà)評(píng)估時(shí)間 */mPaint.setAlpha(160);mPaint.setTextSize(sp2px(10));mPaint.setColor(Color.BLACK);canvas.drawText(getFormatTimeStr(), mCenterX, mCenterY + dp2px(70), mPaint); } private int dp2px(int dp) {return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,Resources.getSystem().getDisplayMetrics()); } private int sp2px(int sp) {return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp,Resources.getSystem().getDisplayMetrics()); } private SweepGradient generateSweepGradient() {SweepGradient sweepGradient = new SweepGradient(mCenterX, mCenterY,new int[]{Color.argb(0, 255, 255, 255), Color.argb(200, 255, 255, 255)},new float[]{0, calculateRelativeAngleWithValue(mCreditValue) / 360});Matrix matrix = new Matrix();matrix.setRotate(mStartAngle - 1, mCenterX, mCenterY);sweepGradient.setLocalMatrix(matrix);return sweepGradient; } private RadialGradient generateRadialGradient(float x, float y) {return new RadialGradient(x, y, mSparkleWidth / 2f,new int[]{Color.argb(255, 255, 255, 255), Color.argb(80, 255, 255, 255)},new float[]{0.4f, 1},Shader.TileMode.CLAMP); } private float[] getCoordinatePoint(float radius, float angle) {float[] point = new float[2];double arcAngle = Math.toRadians(angle); //將角度轉(zhuǎn)換為弧度if (angle < 90) { point[0] = (float) (mCenterX + Math.cos(arcAngle) * radius); point[1] = (float) (mCenterY + Math.sin(arcAngle) * radius);} else if (angle == 90) { point[0] = mCenterX; point[1] = mCenterY + radius;} else if (angle > 90 && angle < 180) { arcAngle = Math.PI * (180 - angle) / 180.0; point[0] = (float) (mCenterX - Math.cos(arcAngle) * radius); point[1] = (float) (mCenterY + Math.sin(arcAngle) * radius);} else if (angle == 180) { point[0] = mCenterX - radius; point[1] = mCenterY;} else if (angle > 180 && angle < 270) { arcAngle = Math.PI * (angle - 180) / 180.0; point[0] = (float) (mCenterX - Math.cos(arcAngle) * radius); point[1] = (float) (mCenterY - Math.sin(arcAngle) * radius);} else if (angle == 270) { point[0] = mCenterX; point[1] = mCenterY - radius;} else { arcAngle = Math.PI * (360 - angle) / 180.0; point[0] = (float) (mCenterX + Math.cos(arcAngle) * radius); point[1] = (float) (mCenterY - Math.sin(arcAngle) * radius);}return point; } /** * 相對(duì)起始角度計(jì)算所對(duì)應(yīng)的角度大小 */ private float calculateRelativeAngleWithValue(int value) {float degreePerSection = 1f * mSweepAngle / mSection;if (value > 6) { return 8 * degreePerSection + 2 * degreePerSection / 250 * (value - 6);} else if (value > 5) { return 6 * degreePerSection + 2 * degreePerSection / 50 * (value - 5);} else if (value > 4) { return 4 * degreePerSection + 2 * degreePerSection / 50 * (value - 4);} else if (value > 3) { return 2 * degreePerSection + 2 * degreePerSection / 50 * (value - 3);} else { return 2 * degreePerSection / 200 * (value - 1);} } /** * 信用分對(duì)應(yīng)描述 */ private String calculateCreditDescription() {if (mSolidCreditValue > 6) { return '';} else if (mSolidCreditValue > 5) { return '';} else if (mSolidCreditValue > 4) { return '';} else if (mSolidCreditValue > 3) { return '';}return ''; } private SimpleDateFormat mDateFormat; private String getFormatTimeStr() {if (mDateFormat == null) { mDateFormat = new SimpleDateFormat('yyyy.MM.dd HH:mm', Locale.CHINA);}return String.format('', mDateFormat.format(new Date()));//return String.format('監(jiān)測(cè)日期:%s', '2020-05-04'); } public int getCreditValue() {return mCreditValue; } /** * 設(shè)置值 * * @param creditValue */ public void setCreditValue(int creditValue) {if (mSolidCreditValue == creditValue || creditValue < mMin || creditValue > mMax) { return;}mSolidCreditValue = creditValue;mCreditValue = creditValue;postInvalidate(); } /** * 設(shè)置并播放動(dòng)畫(huà) * * @param creditValue 值 */ public void setCreditValueWithAnim(int creditValue) {if (creditValue < mMin || creditValue > mMax || !isAnimFinish) { return;}mSolidCreditValue = creditValue;ValueAnimator creditValueAnimator = ValueAnimator.ofInt(1, mSolidCreditValue);creditValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) {mCreditValue = (int) animation.getAnimatedValue();postInvalidate(); }});// 計(jì)算最終值對(duì)應(yīng)的角度,以掃過(guò)的角度的線性變化來(lái)播放動(dòng)畫(huà)float degree = calculateRelativeAngleWithValue(mSolidCreditValue);ValueAnimator degreeValueAnimator = ValueAnimator.ofFloat(mStartAngle, mStartAngle + degree);degreeValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) {mAngleWhenAnim = (float) animation.getAnimatedValue(); }});@SuppressLint('ObjectAnimatorBinding') ObjectAnimator colorAnimator = ObjectAnimator.ofInt(this, 'mBackgroundColor', mBgColors[0], mBgColors[0]);// 實(shí)時(shí)信用值對(duì)應(yīng)的背景色的變化long delay = 1000;if (mSolidCreditValue > 6) { colorAnimator.setIntValues(mBgColors[0], mBgColors[1], mBgColors[2], mBgColors[3], mBgColors[4]); delay = 3000;} else if (mSolidCreditValue > 5) { colorAnimator.setIntValues(mBgColors[0], mBgColors[1], mBgColors[2], mBgColors[3]); delay = 2500;} else if (mSolidCreditValue > 4) { colorAnimator.setIntValues(mBgColors[0], mBgColors[1], mBgColors[2]); delay = 2000;} else if (mSolidCreditValue > 3) { colorAnimator.setIntValues(mBgColors[0], mBgColors[1]); delay = 1500;}colorAnimator.setEvaluator(new ArgbEvaluator());colorAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) {mBackgroundColor = (int) animation.getAnimatedValue(); }});AnimatorSet animatorSet = new AnimatorSet();animatorSet.setDuration(delay).playTogether(creditValueAnimator, degreeValueAnimator, colorAnimator);animatorSet.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animation) {super.onAnimationStart(animation);isAnimFinish = false; } @Override public void onAnimationEnd(Animator animation) {super.onAnimationEnd(animation);isAnimFinish = true; } @Override public void onAnimationCancel(Animator animation) {super.onAnimationCancel(animation);isAnimFinish = true; }});animatorSet.start(); }}

在color中添加顏色值:

<color name='color_red'>#FF5722</color><color name='color_orange'>#FF9800</color><color name='color_yellow'>#FFC107</color><color name='color_green'>#3FB830</color><color name='color_blue'>#00BAED</color>

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持好吧啦網(wǎng)。

標(biāo)簽: Android
相關(guān)文章:
主站蜘蛛池模板: 亚洲国产成人久久精品影视 | japanese色系国产在线高清 | 中文字幕一区二区在线视频 | 成年女人免费视频播放成年m | 亚洲国产精品综合久久网络 | 国产精品一区二区三区高清在线 | 自拍偷自拍亚洲精品10p | 国产一区二区免费播放 | 怡红院宜春院 | 国产高清亚洲精品26u | 国产在线观看精品香蕉v区 国产在线观看免费人成小说 | 精品无码久久久久久国产 | 成人亚洲精品777777 | 成熟的女性强烈交性视频 | 日日干日日操日日射 | 91香蕉国产线在线观看免费 | 性欧美video另类bd | 欧美成年免费a级 | 欧美精品一区二区三区视频 | 成年男女的免费视频网站 | 国产日韩欧美久久久 | 日本亚州在线播放精品 | 国产精品久久久久精 | 国产精品久久免费视频 | 国产免费久久 | 国产一区二区三区四区五区 | av毛片免费看 | 波多野结衣一级片 | 免费的成人a视频在线观看 免费的毛片 | 国产精品久久久久久一级毛片 | 一本色道久久99一综合 | 日本美女福利视频 | 色婷婷国产精品欧美毛片 | 欧美精选欧美极品 | 精品一区二区三区视频在线观看免 | 激情综| 亚洲一级高清在线中文字幕 | 亚洲精品免费视频 | 久久这里有精品视频 | 亚洲 欧美 都市 自拍 在线 | 欧美一区二区在线播放 |