自定義view之圓點progressBar

上一篇博客弄了個自定義樣式的等待對話框,裏面那個圓形progressBar只是隨便用了環形的shape來佈局,後來發現真的醜得不要不要的,所以手動畫了一個圓點progress。y由於個人是不喜歡在開發APP的時候放大型的圖片或者gif圖這些會增加APP體積之類的東西,所以那些規則的圖形和動畫基本上都喜歡用代碼畫出來,雖然有點磨時間,但最後項目後期和做ios版本的同事相比,喜歡放圖片的同事做出來的APP體積有20多M,而我做出來的只有4.5M,確實有點成就感。

好吧,不多說,封裝了以後直接用。

效果圖:



自定義view的步驟就不多說了,前面的博客已經寫過了,所以直接上代碼,代碼裏註釋很清楚:


無非就是在大圓軌跡上根據畫小圓,關鍵是需要用到幾何的正餘弦計算。



attrs.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="CircleProgress">
        <attr name="numOfCircles" format="integer"/>
        <attr name="maxRadius" format="dimension"/>
        <attr name="minRadius" format="dimension"/>
        <attr name="rotateSpeedInMillis" format="integer"/>
        <attr name="isClockwise" format="boolean"/>
        <attr name="circleColor" format="color"/>
    </declare-styleable>    
    
</resources>

CircleProgress.java

public class CircleProgress extends View{
	
	//小圓的個數
	private int numOfCircles;
	//最大圓半徑
	private int maxRadius;
	//最小圓半徑
	private int minRadius;
	//旋轉速度
	private int rotateSpeedInMillis;
	//是否順時針旋轉
	private boolean isClockwise;
	//小圓的顏色
	private int circleColor;
	
	private Paint paint;
	
	private float rotateDegrees;
	private int numOfRotate;

	public CircleProgress(Context context, AttributeSet attrs, int defStyleAttr) {
		super(context, attrs, defStyleAttr);
		// TODO Auto-generated constructor stub
		TypedArray array=context.obtainStyledAttributes(attrs, R.styleable.CircleProgress);
		
		numOfCircles=array.getInt(R.styleable.CircleProgress_numOfCircles, 10);
		maxRadius=array.getDimensionPixelSize(R.styleable.CircleProgress_maxRadius, dp2px(10));
		minRadius=array.getDimensionPixelSize(R.styleable.CircleProgress_minRadius, dp2px(2));
		rotateSpeedInMillis=array.getInt(R.styleable.CircleProgress_rotateSpeedInMillis, 200);
		isClockwise=array.getBoolean(R.styleable.CircleProgress_isClockwise, true);
		circleColor=array.getColor(R.styleable.CircleProgress_circleColor, Color.BLACK);
		
		array.recycle();
	
		paint=new Paint();
		paint.setStyle(Style.FILL);
		paint.setAntiAlias(true);
		paint.setColor(circleColor);
		
		//view每次旋轉的角度
		rotateDegrees=360/numOfCircles;
		//旋轉的週期爲小圓的個數
		numOfRotate=0;

	}

	public CircleProgress(Context context, AttributeSet attrs) {
		this(context, attrs, 0);
		// TODO Auto-generated constructor stub
	}

	public CircleProgress(Context context) {
		this(context, null);
		// TODO Auto-generated constructor stub
	}

	@Override
	protected void onDraw(Canvas canvas) {
		// TODO Auto-generated method stub
		
		//按一定角度旋轉畫布canvas,當旋轉週期==小圓個數時重置
		if(numOfRotate==numOfCircles){
			numOfRotate=0;
		}
		
		//根據旋轉的方向旋轉畫布canvas,然後再畫小圓
		if(isClockwise){
			canvas.rotate(rotateDegrees*numOfRotate, getWidth()/2, getHeight()/2);
		}else{
			canvas.rotate(-rotateDegrees*numOfRotate, getWidth()/2, getHeight()/2);
		}
		
		//記錄旋轉的次數,下次invalidat()重繪時就可以使用新的角度旋轉canvas,使小圓產生旋轉的感覺
		numOfRotate++;
		
		//取View最短邊,並減去最大圓的半徑,得到所有圓所在的圓路徑的半徑
		int radius=(getWidth()>getHeight()?getHeight():getWidth())/2-maxRadius;
		//每個小圓的半徑增量
		float radiusIncrement=(float)(maxRadius-minRadius)/numOfCircles;
		//每隔多少度繪製一個小圓,弧度制		
		double angle=2*Math.PI/numOfCircles;
		
		//按位置畫小圓
		//每個小圓的位置可以由正弦餘弦函數求出,並且每個小圓半徑依次遞增,若反方向則依次遞減
		if(isClockwise){			
			for(int i=0; i<numOfCircles; i++){
				float x=(float) (getWidth()/2+Math.cos(i*angle)*radius);
				float y=(float) (getHeight()/2-Math.sin(i*angle)*radius);
				canvas.drawCircle(x, y, maxRadius-radiusIncrement*i, paint);				
			}
		}else{
			for(int i=0; i<numOfCircles; i++){
				float x=(float) (getWidth()/2+Math.cos(i*angle)*radius);
				float y=(float) (getHeight()/2-Math.sin(i*angle)*radius);
				canvas.drawCircle(x, y, minRadius+radiusIncrement*i, paint);				
			}
		}
		
		
		//旋轉間隔,即progressBar的旋轉速度
		postDelayed(new Runnable() {
			
			@Override
			public void run() {
				// TODO Auto-generated method stub
				invalidate(); 
			}
		}, rotateSpeedInMillis);
	}

	//dp轉px函數
	private int dp2px(int dp){
		return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics());
	}
}

代碼下載: github



發佈了33 篇原創文章 · 獲贊 50 · 訪問量 21萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章