自定義View 圓形進度條
目錄

自定義View 圓形進度條.png
效果
按照慣例,放上效果圖

自定義View 圓形進度條.gif
前言
上一篇 文章把斷點續傳的功能分享了一下,有興趣的朋友可以看一看。接下來就給大家分享一下自定義View 圓形載入條。
正文
自定義View CirclePercentView
public class CirclePercentView extends View { //圓的半徑 private float mRadius; //色帶的寬度 private float mStripeWidth; //總體大小 private int mHeight; private int mWidth; //動畫位置百分比進度 private int mCurPercent; //實際百分比進度 private int mPercent; //圓心座標 private float x; private float y; //要畫的弧度 private int mEndAngle; //小圓的顏色 private int mSmallColor; //大圓顏色 private int mBigColor; //中心百分比文字大小 private float mCenterTextSize; public CirclePercentView(Context context) { this(context, null); } public CirclePercentView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public CirclePercentView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CirclePercentView, defStyleAttr, 0); mStripeWidth = a.getDimension(R.styleable.CirclePercentView_stripeWidth, PxUtils.dpToPx(30, context)); mCurPercent = a.getInteger(R.styleable.CirclePercentView_percent, 0); mSmallColor = a.getColor(R.styleable.CirclePercentView_smallColor, 0xffafb4db); mBigColor = a.getColor(R.styleable.CirclePercentView_bigColor, 0xff6950a1); mCenterTextSize = a.getDimensionPixelSize(R.styleable.CirclePercentView_centerTextSize, PxUtils.spToPx(20, context)); mRadius = a.getDimensionPixelSize(R.styleable.CirclePercentView_radius, PxUtils.dpToPx(100, context)); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { //獲取測量模式 int widthMode = MeasureSpec.getMode(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); //獲取測量大小 int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); if (widthMode == MeasureSpec.EXACTLY && heightMode == MeasureSpec.EXACTLY) { mRadius = widthSize / 2; x = widthSize / 2; y = heightSize / 2; mWidth = widthSize; mHeight = heightSize; } if (widthMode == MeasureSpec.AT_MOST && heightMode == MeasureSpec.AT_MOST) { mWidth = (int) (mRadius * 2); mHeight = (int) (mRadius * 2); x = mRadius; y = mRadius; } setMeasuredDimension(mWidth, mHeight); } @Override protected void onDraw(Canvas canvas) { mEndAngle = (int) (mCurPercent * 3.6);//mCurPercent=0~100.則mEndAngle=0~360. //繪製大圓 Paint bigCirclePaint = new Paint(); bigCirclePaint.setAntiAlias(true);//抗鋸齒,同:別名alias. bigCirclePaint.setColor(mBigColor); canvas.drawCircle(x, y, mRadius, bigCirclePaint); //餅狀圖, Paint sectorPaint = new Paint(); sectorPaint.setColor(mSmallColor); sectorPaint.setAntiAlias(true); //精度不一樣。Rect是使用int型別作為數值,RectF是使用float型別作為數值。 RectF rect = new RectF(0, 0, mWidth, mHeight); //圓弧arc,即扇形. canvas.drawArc(rect, 0, mEndAngle, true, sectorPaint); ////繪製小圓,顏色 同 大圓. //Paint smallCirclePaint = new Paint(); //smallCirclePaint.setAntiAlias(true); //smallCirclePaint.setColor(mBigColor); //canvas.drawCircle(x, y, mRadius - mStripeWidth, smallCirclePaint); //繪製文字 Paint textPaint = new Paint(); String text = mCurPercent + "%"; textPaint.setTextSize(mCenterTextSize); float textLength = textPaint.measureText(text); textPaint.setColor(Color.WHITE); canvas.drawText(text, x - textLength / 2, y, textPaint); } //外部設定百分比數 public void setPercent(int percent) { if (percent > 100) { throw new IllegalArgumentException("percent must less than 100!"); } setCurPercent(percent); } //內部設定百分比 用於動畫效果 private void setCurPercent(int percent) { mPercent = percent; new Thread(new Runnable() { @Override public void run() { int sleepTime = 1; for (int i = 0; i <= mPercent; i++) { if (i % 20 == 0) { sleepTime += 2; } try { Thread.sleep(sleepTime); } catch (InterruptedException e) { e.printStackTrace(); } mCurPercent = i; CirclePercentView.this.postInvalidate(); } } }).start(); } }
-
首先自定義View ,肯定是要繼承View類的
-
CirclePercentView()
類中實現了三個構造方法,前兩個方法呼叫第三個方法,我們在第三個方法中初始化自定義的變數,也就是相應的顏色,半徑,寬度等等, -
onMeasure()
方法,繼承自View,在方法中獲得了檢視的寬度和高度,根據高度和寬度,定義了相應的自定義高度和寬度,以及圓的座標位置。 -
onDraw()
方法,依舊重寫於VIew 類中,這個方法就是繪製檢視,比較麻煩;- 第一步設定了要畫的弧度
- 一共3個
Plint
和一個Canvas
;bigCirclePaint
繪製大圓,設定了抗鋸齒和顏色,sectorPaint
餅狀圖也就是效果中的扇形,設定了顏色和抗鋸齒,textPaint
文字,中間的數字,cancas
就是畫布,plint就相當於畫筆,我們把畫筆畫在畫布上就成功的現實了上面的效果
-
最後兩個方法:外部百分比和內部的百分比,內部的百分比有一個動畫效果;外部就是給外部留下了方法可以呼叫;
PxUtils
/** * 用於px和dp,sp的轉換工具 */ public class PxUtils { public static int dpToPx(int dp, Context context) { return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, context.getResources().getDisplayMetrics()); } public static int spToPx(int sp,Context context) { return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, context.getResources().getDisplayMetrics()); } }
此方法就是dp和sp轉為px的方法
主方法 MainActivity
public class MainActivity extends AppCompatActivity { private Button mButton; private CirclePercentView mCirclePercentView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mCirclePercentView = (CirclePercentView) findViewById(R.id.circleView); mButton = (Button) findViewById(R.id.button); mButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { int n = (int)(1*100); mCirclePercentView.setPercent(n); } }); } }
- 定義了一個自定義View,一個Button
- 通過點選事件設定進度
activity_main 檢視
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.wingsofts.circlepercentview.MainActivity"> <com.wingsofts.circlepercentview.CirclePercentView android:id="@+id/circleView" app:stripeWidth="15dp" app:centerTextSize="16sp" app:percent="45" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <Button android:id="@+id/button" android:text="change" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout>
總結
其實自定義View就是很簡單的東西 ,我們可以自己動手操作一下就可以了,主要就是畫筆和畫布之間,然後動態效果就是通過執行緒更新UI;就每次都重新繪畫一下檢視。