這節中,咱們咱們來討論微盾上界面上實現的二三事。這也是這個項目的重頭戲。android
界面上咱們要作一個什麼效果,一個倒計時的效果了,這個倒計時效果之後用的不少,但願對你們有幫助。canvas
我這裏佈局方式用到了幀佈局的方式,一個是所謂的錶盤的狀況,一個是倒計時的秒針, 相應的佈局文件以下了:ide
<FrameLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" > <com.itcast.vdunx.RingView android:layout_width="@dimen/ring_view_width" android:layout_height="@dimen/ring_view_height" > </com.itcast.vdunx.RingView> <com.itcast.vdunx.CountdownIndicator android:id="@+id/pb_progress" android:layout_width="@dimen/countdown_indicator_width" android:layout_height="@dimen/countdown_indicator_height" android:layout_gravity="center" > </com.itcast.vdunx.CountdownIndicator> </FrameLayout>
那個RingView是我自定義的錶盤控件,它即在手機的界面上畫了一個園,而這個CountdownIndicator便是一個倒計時控件,它是一個什麼,一個扇形,一個隨着時間的變化而不斷改變本身大小的扇形。這兩個控件的原理是什麼了,咱們來窺探它一下原貌了。函數
首先看一下RingVieW的源代碼:佈局
Paint paint; Context ctx; public RingView(Context context, AttributeSet attrs) { super(context, attrs); paint = new Paint(); this.paint.setAntiAlias(true);//沒有鋸齒 this.paint.setStyle(Paint.Style.STROKE);//畫空心 ctx = context; } @Override protected void onDraw(Canvas paramCanvas) { float center = getWidth()/2; int innerCircle = dip2px(ctx,83); //設置內圓半徑 int ringWidth = dip2px(ctx,5); //設置圓環寬度 //繪製內圓 this.paint.setARGB(155, 167, 190, 206); this.paint.setStrokeWidth(2);//設置線條寬度 paramCanvas.drawCircle(center,center, innerCircle, this.paint);//innerCircle:半徑 //繪製圓環 this.paint.setARGB(255, 212 ,225, 233); this.paint.setStrokeWidth(ringWidth);//中間圓環寬度 paramCanvas.drawCircle(center,center, innerCircle+1+ringWidth/2, this.paint); //繪製外圓 this.paint.setARGB(155, 167, 190, 206); this.paint.setStrokeWidth(2); paramCanvas.drawCircle(center,center, innerCircle+ringWidth, this.paint); } /** * 根據手機的分辨率從 dp 的單位 轉成爲 px(像素) */ public static int dip2px(Context context, float dpValue) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (dpValue * scale + 0.5f); }
經過上面的源代碼,咱們能夠清晰看出來了,這個只是經過相應畫筆在指定的圓心位置按照固定位置來畫出來相應的圓環。動畫
而CountdownIndicator控件則比上述的控件園複雜一點了,首先仍是看代碼:this
public class CountdownIndicator extends View { Paint paint; double phase; public CountdownIndicator(Context context, AttributeSet attrs) { super(context, attrs); this.paint = new Paint(); this.paint.setAntiAlias(true); // 在此處沒法直接得到控件的寬高,只能從資源文件中讀取 float x = context.getResources().getDimension( R.dimen.countdown_indicator_width) / 2;// 返回的是像素值 float y = context.getResources().getDimension( R.dimen.countdown_indicator_height) / 2; RadialGradient rg = new RadialGradient(x, y, y, Color.argb(255, 143, 201, 233), Color.argb(255, 166, 212, 235), TileMode.MIRROR);// 漸變 this.paint.setShader(rg); } @Override protected void onDraw(Canvas canvas) { float f1 = (float) (phase * 360); float f2 = 270 - f1; RectF localRectF = new RectF(0, 0, getWidth(), getHeight()); canvas.drawArc(localRectF, f2, f1, true, paint);// f2:起始角度,f1:掃描幅度 } public void setPhase(double phase) { if (phase < 0 || phase > 1) { throw new IllegalArgumentException(); } this.phase = phase; invalidate(); }
這個類主要就是Phase這個角度,而他掃描的幅度這是一個起始角度,起始角度是一個o-1的浮點數*360,而相應的掃描的幅度根據相應數據三角函數的方法是270-起始角度了,這樣就獲得一個倒計時秒盤的結果。spa
有了這兩個類以後,根據相應的時間控件計時以後,最終的計時的效果是這樣的:3d
這個動畫製做過程你們明白吧。code