Android 漸變圓環,圓形進度條效果實現

      網友投稿 1207 2025-03-31

      最近做了一個功能,里面涉及到了漸變圓形的需求。就是一個顏色可以漸變的圓環,最后實現的效果如下圖:

      左圖是帶漸變效果,右圖是不帶漸變效果。原理還是繪圖,Canvas可以繪制的對象有:弧線(arcs)、填充顏色(argb和color)、

      Bitmap、圓(circle和oval)、點(point)、線(line)、矩形(Rect)、圖片(Picture)、圓角矩形 (RoundRect)、文本(text)、

      頂點(Vertices)、路徑(path)。通過組合這些對象我們可以畫出一些簡單有趣的界面出來,但是光有這些功能還是不夠的,

      如果我要畫一個儀表盤(數字圍繞顯示在一個圓圈中)呢? 幸好Android還提供了一些對Canvas位置轉換的方法:rorate、scale、

      translate、skew(扭曲)等,而且它允許你通過獲得它的轉換矩陣對象(getMatrix方法,不知道什么是轉換矩陣?)

      直接操作它。這些操作就像是雖然你的筆還是原來的地方畫,但是畫紙旋轉或者移動了,所以你畫的東西的方位就產生變化。

      為了方便一些轉換操作,Canvas 還提供了保存和回滾屬性的方法(save和restore),比如你可以先保存目前畫紙的位置(save),

      然后旋轉90度,向下移動100像素后畫一些圖形,畫完后調用restore方法返回到剛才保存的位置。

      話不多說,上代碼

      核心類:

      自定義控件 CircleProgressBar

      package com.jky.mobile_xmxt.view;

      import android.content.Context;

      import android.graphics.Canvas;

      import android.graphics.Color;

      import android.graphics.Paint;

      import android.graphics.RectF;

      import android.graphics.SweepGradient;

      import android.util.AttributeSet;

      import android.view.View;

      import android.view.Animation.Animation;

      import android.view.animation.Transformation;

      import com.jky.mobile_xmxt.R;

      import java.text.DecimalFormat;

      /**

      * 圓盤計步圖表

      */

      public class CircleProgressBar extends View {

      private RectF mWheelRect = new RectF();

      private Paint mDefaultWheelPaint;

      private Paint mFinishWheelPaint;

      private Paint mCenterWheelPaint;

      private Paint mTitlePaint, mStepPaint, mTargetPaint;

      private float mCircleStrokeWidth;

      private float mSweepAnglePer;

      private float mPercent;

      private int mStepNum, mCurrStepNum;

      private float pressExtraStrokeWidth;

      private BarAnimation mAnim;

      private int mMaxStepNum;// 默認最大步數

      private float mTitleY, mStepY, mTargetY;

      private DecimalFormat mDecimalFormat = new DecimalFormat("#.0");// 格式為保留小數點后一位

      public static String GOAL_STEP;

      public static String PERCENT;

      public CircleProgressBar(Context context) {

      super(context);

      init(null, 0);

      }

      public CircleProgressBar(Context context, AttributeSet attrs) {

      super(context, attrs);

      init(attrs, 0);

      }

      public CircleProgressBar(Context context, AttributeSet attrs, int defStyle) {

      super(context, attrs, defStyle);

      init(attrs, defStyle);

      }

      private void init(AttributeSet attrs, int defStyle) {

      mFinishWheelPaint = new Paint();

      mFinishWheelPaint.setColor(Color.rgb(100, 113, 205));

      mFinishWheelPaint.setStyle(Paint.Style.STROKE);// 空心

      mFinishWheelPaint.setStrokeCap(Paint.Cap.ROUND);// 圓角畫筆

      mFinishWheelPaint.setAntiAlias(true);// 去鋸齒

      mCenterWheelPaint = new Paint();

      mCenterWheelPaint.setColor(Color.rgb(243, 243, 243));

      mCenterWheelPaint.setStyle(Paint.Style.STROKE);

      mCenterWheelPaint.setStrokeCap(Paint.Cap.ROUND);

      mCenterWheelPaint.setAntiAlias(true);

      mDefaultWheelPaint = new Paint();

      mDefaultWheelPaint.setColor(Color.rgb(127, 127, 127));

      mDefaultWheelPaint.setStyle(Paint.Style.STROKE);

      mDefaultWheelPaint.setStrokeCap(Paint.Cap.ROUND);

      mDefaultWheelPaint.setAntiAlias(true);

      mTitlePaint = new Paint();

      mTitlePaint.setAntiAlias(true);

      mTitlePaint.setColor(Color.WHITE);

      mStepPaint = new Paint();

      mStepPaint.setAntiAlias(true);

      mStepPaint.setColor(Color.WHITE);

      mTargetPaint = new Paint();

      mTargetPaint.setAntiAlias(true);

      mTargetPaint.setColor(Color.WHITE);

      mAnim = new BarAnimation();

      }

      @Override

      protected void onDraw(Canvas canvas) {

      canvas.drawArc(mWheelRect, 0, 359, false, mDefaultWheelPaint);

      canvas.drawArc(mWheelRect, 0, 359, false, mCenterWheelPaint);

      canvas.drawArc(mWheelRect, 90, mSweepAnglePer, false, mFinishWheelPaint);

      // canvas.drawText("步數", mWheelRect.centerX() - (mTitlePaint.measureText("步數") / 2), mTitleY,

      // mTitlePaint);

      canvas.drawText(mCurrStepNum + "",

      mWheelRect.centerX() - (mStepPaint.measureText(String.valueOf(mCurrStepNum)) / 2), mStepY,

      mStepPaint);

      String description = "";

      float percent = getPercent();

      if(percent > 0.5){

      description ="嚴重污染";

      }else if(percent<0.5){

      description ="中等污染";

      }else{

      description ="普通污染";

      }

      canvas.drawText(description , mWheelRect.centerX() -

      (mTargetPaint.measureText(description) / 2), mTargetY, mTargetPaint);

      SweepGradient sweepGradient = new SweepGradient(mWheelRect.centerX(), mWheelRect.centerY(),

      new int[]{getResources().getColor(R.color.color_environment_severe), getResources().getColor(R.color.color_environment_serious),

      getResources().getColor(R.color.color_environment_excellent),

      getResources().getColor(R.color.color_environment_good), getResources().getColor(R.color.color_environment_mild),

      getResources().getColor(R.color.color_environment_moderate)}, null);

      mFinishWheelPaint.setShader(sweepGradient);

      }

      @Override

      protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

      int height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);

      int width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);

      int min = Math.min(width, height);// 獲取View最短邊的長度

      setMeasuredDimension(min, min);// 強制改View為以最短邊為長度的正方形

      mCircleStrokeWidth = getTextScale(15, min);// 圓弧的寬度

      pressExtraStrokeWidth = getTextScale(10, min);// 圓弧離矩形的距離

      mWheelRect.set(mCircleStrokeWidth + pressExtraStrokeWidth, mCircleStrokeWidth + pressExtraStrokeWidth,

      min - mCircleStrokeWidth - pressExtraStrokeWidth, min - mCircleStrokeWidth - pressExtraStrokeWidth);// 設置矩形

      mTitlePaint.setTextSize(getTextScale(60, min));

      mStepPaint.setTextSize(getTextScale(120, min));

      mTargetPaint.setTextSize(getTextScale(40, min));

      mTitleY = getTextScale(170, min);

      mStepY = getTextScale(300, min);

      mTargetY = getTextScale(380, min);

      mFinishWheelPaint.setStrokeWidth(mCircleStrokeWidth);

      mCenterWheelPaint.setStrokeWidth(mCircleStrokeWidth);

      mDefaultWheelPaint.setStrokeWidth(mCircleStrokeWidth - getTextScale(2, min));

      mDefaultWheelPaint.setShadowLayer(getTextScale(10, min), 0, 0, Color.rgb(127, 127, 127));// 設置陰影

      }

      /**

      * 進度條動畫

      *

      * @author Administrator

      */

      public class BarAnimation extends Animation {

      /**

      * 每次系統調用這個方法時, 改變mSweepAnglePer,mPercent,stepnumbernow的值,

      * 然后調用postInvalidate()不停的繪制view。

      */

      @Override

      protected void applyTransformation(float interpolatedTime, Transformation t) {

      // if (interpolatedTime < 1.0f) {

      // mPercent = Float.parseFloat(mDecimalFormat.format(interpolatedTime * mStepNum * 100f / mMaxStepNum));// 將浮點值四舍五入保留一位小數

      // mSweepAnglePer = interpolatedTime * mStepNum * 360 / mMaxStepNum;

      // mCurrStepNum = (int) (interpolatedTime * mStepNum);

      // } else {

      mPercent = Float.parseFloat(mDecimalFormat.format(mStepNum * 100f / mMaxStepNum));// 將浮點值四舍五入保留一位小數

      if (mPercent > 100.0f) {

      mPercent = 100.0f;

      }

      PERCENT = String.valueOf(mPercent);

      mSweepAnglePer = mStepNum * 360 / mMaxStepNum;

      mCurrStepNum = mStepNum;

      // }

      requestLayout();

      }

      }

      public float getPercent() {

      return mPercent;

      }

      /**

      * 根據控件的大小改變絕對位置的比例

      *

      * @param n

      * @param m

      * @return

      */

      public float getTextScale(float n, float m) {

      return n / 500 * m;

      }

      /**

      * 更新步數和設置一圈動畫時間

      *

      * @param stepCount

      Android 漸變圓環,圓形進度條效果實現

      * @param time

      */

      public void update(int stepCount, int time) {

      this.mStepNum = stepCount;

      mAnim.setDuration(time);

      // setAnimationTime(time);

      this.startAnimation(mAnim);

      }

      /**

      * @param stepNum

      */

      public void setMaxStepNum(int stepNum) {

      mMaxStepNum = stepNum;

      GOAL_STEP = String.valueOf(mMaxStepNum);

      }

      public void setColor(int color) {

      mFinishWheelPaint.setColor(color);

      mStepPaint.setColor(color);

      }

      /**

      * 設置動畫時間

      *

      * @param time

      */

      public void setAnimationTime(int time) {

      mAnim.setDuration(time * mStepNum / mMaxStepNum);// 按照比例設置動畫執行時間

      }

      }

      xml引用

      android:id="@+id/color_progress_view"

      android:layout_width="match_parent"

      android:layout_height="0dp"

      android:layout_weight="6"

      />

      Activity調用方法

      color_progress_view = (CircleProgressBar)view.findViewById(R.id.color_progress_view);

      color_progress_view.setMaxStepNum(500);

      color_progress_view.update(470,1000);

      由于和調用其他控件方法類似,姑且省去了很多其他業務邏輯代碼,代碼不是特別復雜,修改起來也很方便(修改顏色,總量及比例等),所以只粘貼核心相關的代碼,希望可以幫助到大家。

      如果大家還有其他問題,也歡迎大家加入我的qq群交流討論:

      開發一群:454430053開發二群:537532956

      Android Canvas

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:如何自動調整注釋框的大小以適合Excel中的內容?
      下一篇:如何在word中繪制表格(word中怎么繪制表格)
      相關文章
      亚洲伊人久久精品影院| 亚洲中文字幕日本无线码| 午夜亚洲乱码伦小说区69堂| 亚洲日韩国产精品第一页一区| 亚洲第一网站男人都懂| 久久亚洲精品高潮综合色a片| 亚洲精品福利网站| 亚洲精品在线播放| 亚洲日本视频在线观看| 亚洲网站视频在线观看| 亚洲精品福利在线观看| 亚洲精品人成电影网| 亚洲成人在线免费观看| 亚洲剧场午夜在线观看| 亚洲AV无码久久久久网站蜜桃| 亚洲1234区乱码| 亚洲欧美日韩一区二区三区在线| 亚洲女女女同性video| 欧美亚洲国产SUV| 亚洲国产成人久久综合碰| 亚洲欧洲精品成人久久奇米网| 久久久久无码专区亚洲av | 亚洲人成人伊人成综合网无码| 亚洲综合av一区二区三区不卡 | 久久久亚洲欧洲日产国码二区| 亚洲午夜精品久久久久久人妖| 亚洲综合激情六月婷婷在线观看| 亚洲欧洲日韩综合| 国内精品久久久久影院亚洲| 亚洲另类无码专区丝袜| 在线播放亚洲精品| 国产亚洲?V无码?V男人的天堂| 国产亚洲3p无码一区二区| 亚洲免费在线视频| 亚洲人成黄网在线观看| 亚洲色偷偷综合亚洲av78| 一本久到久久亚洲综合| 亚洲人成在线播放网站| 亚洲情a成黄在线观看动漫尤物| 亚洲国产日韩在线人成下载| 亚洲欧美日韩一区二区三区在线|