您好,登錄后才能下訂單哦!
這篇文章給大家分享的是有關Android怎么實現簡單時鐘View的方法的內容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。
通過Canvas的平移與旋轉簡化繪圖邏輯是一個非常有用的技巧,下面的時鐘view就是利用這個方法完成的,省去了使用三角函數計算坐標的麻煩。
package com.example.swt369.simpleclock; import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; import android.support.annotation.Nullable; import android.util.AttributeSet; import android.view.View; import android.view.ViewTreeObserver; import android.widget.Toast; import java.util.Calendar; /** * Created by swt369 on 2017/8/20. */ public class ClockView extends View { //時鐘各個部件的長度 private float mScaleLengthLong; private float mScaleLengthShort; private float mTickLengthHour; private float mTickLengthMinute; private float mTickLengthSecond; //view的寬和高 private float mWidth; private float mHeight; //時鐘半徑 private float mRadius; //繪制各部件時用的Paint private Paint mPaintScaleLong; private Paint mPaintScaleShort; private Paint mPaintOutline; private Paint mPaintNum; private Paint mPaintTickHour; private Paint mPaintTickMinute; private Paint mPaintTickSecond; private ViewTreeObserver.OnPreDrawListener onPreDrawListener; public ClockView(final Context context, @Nullable AttributeSet attrs) { super(context, attrs); onPreDrawListener = new ViewTreeObserver.OnPreDrawListener() { //獲取view寬高并計算各個部件的長度 @Override public boolean onPreDraw() { mWidth = getMeasuredWidth(); mHeight = getMeasuredHeight(); mRadius = Math.min(mWidth,mHeight) / 2 * 0.95f; mScaleLengthLong = mRadius * 0.1f; mScaleLengthShort = mRadius * 0.05f; mTickLengthHour = mRadius * 0.3f; mTickLengthMinute = mRadius * 0.45f; mTickLengthSecond = mRadius * 0.6f; return true; } }; getViewTreeObserver().addOnPreDrawListener(onPreDrawListener); //點擊顯示具體時間 setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Calendar calendar = Calendar.getInstance(); String time = String.format("當前時間:%02d:%02d:%02d", calendar.get(Calendar.HOUR_OF_DAY),calendar.get(Calendar.MINUTE),calendar.get(Calendar.SECOND)); Toast.makeText(context,time, Toast.LENGTH_SHORT).show(); } }); //初始化所有Paint對象 initializePaints(); } @Override protected void onDraw(Canvas canvas) { if(mWidth == 0 || mHeight == 0){ return; } if(onPreDrawListener != null){ getViewTreeObserver().removeOnPreDrawListener(onPreDrawListener); onPreDrawListener = null; } //繪制時鐘 drawClock(canvas); //一秒后重繪 postInvalidateDelayed(1000); } private void drawClock(Canvas canvas) { //保存原始狀態 canvas.save(); //將坐標系原點移到中心,并逆時針旋轉90度。完成后x軸朝上。 canvas.translate(mWidth / 2,mHeight / 2); canvas.rotate(-90); //畫外圍輪廓 canvas.drawCircle(0,0,mRadius, mPaintOutline); //畫刻度 for(int i = 0 ; i < 12 ; i++){ String num = String.valueOf(i == 0 ? 12 : i); if(i % 3 == 0){ canvas.drawLine(mRadius,0,mRadius - mScaleLengthLong,0, mPaintScaleLong); }else { canvas.drawLine(mRadius,0,mRadius - mScaleLengthShort,0, mPaintScaleShort); } canvas.drawText(num,mRadius - mScaleLengthLong - mPaintNum.measureText(num) * 2,0, mPaintNum); //順時針旋轉30度 canvas.rotate(30); } Calendar calendar = Calendar.getInstance(); //畫時針 int hour = calendar.get(Calendar.HOUR); canvas.save(); canvas.rotate(hour * 30); canvas.drawLine(0,0,mTickLengthHour,0,mPaintTickHour); canvas.restore(); //畫分針 int minute = calendar.get(Calendar.MINUTE); canvas.save(); canvas.rotate(minute * 6); canvas.drawLine(0,0,mTickLengthMinute,0,mPaintTickMinute); canvas.restore(); //畫秒針 int second = calendar.get(Calendar.SECOND); canvas.save(); canvas.rotate(second * 6); canvas.drawLine(0,0,mTickLengthSecond,0,mPaintTickSecond); canvas.restore(); //恢復原始狀態 canvas.restore(); } private void initializePaints(){ mPaintScaleLong = new Paint(); mPaintScaleLong.setAntiAlias(true); mPaintScaleLong.setStrokeWidth(5); mPaintScaleShort = new Paint(); mPaintScaleShort.setAntiAlias(true); mPaintScaleShort.setStrokeWidth(3); mPaintOutline = new Paint(); mPaintOutline.setStyle(Paint.Style.STROKE); mPaintOutline.setAntiAlias(true); mPaintOutline.setStrokeWidth(5); mPaintNum = new Paint(); mPaintNum.setTextSize(30); mPaintTickHour = new Paint(); mPaintTickHour.setAntiAlias(true); mPaintTickHour.setStrokeWidth(6); mPaintTickMinute = new Paint(); mPaintTickMinute.setAntiAlias(true); mPaintTickMinute.setStrokeWidth(4); mPaintTickSecond = new Paint(); mPaintTickSecond.setAntiAlias(true); mPaintTickSecond.setStrokeWidth(2); } }
代碼注釋已經比較詳細了,下面把比較重要的部分再說明一下:
//保存原始狀態 canvas.save(); //省略中間部分... //恢復原始狀態 canvas.restore();
在繪圖開始時調用canvas.save(),可以保存下未經任何平移、旋轉操作的原始畫布狀態。在所有繪圖工作完成后調用canvas.restore(),可以恢復到上一次保存的狀態(類似進出棧的感覺)。
//將坐標系原點移到中心,并逆時針旋轉90度。完成后x軸朝上。 canvas.translate(mWidth / 2,mHeight / 2); canvas.rotate(-90);
畫布的平移與旋轉可能比較抽象,可以想象成坐標系的平移與旋轉。調用canvas.translate(dx,dy)相當于將坐標原點向x,y方向移動了dx,dy的距離,調用canvas.rotate(degree)相當于坐標系順時針旋轉了degree°。
//畫刻度 for(int i = 0 ; i < 12 ; i++){ String num = String.valueOf(i == 0 ? 12 : i); if(i % 3 == 0){ canvas.drawLine(mRadius,0,mRadius - mScaleLengthLong,0, mPaintScaleLong); }else { canvas.drawLine(mRadius,0,mRadius - mScaleLengthShort,0, mPaintScaleShort); } canvas.drawText(num,mRadius - mScaleLengthLong - mPaintNum.measureText(num) * 2,0, mPaintNum); //順時針旋轉30度 canvas.rotate(30); }
根據i值決定是畫大刻度(90°的倍數)還是小刻度。每次畫完一條之后將坐標系順時針旋轉30°,這樣保證每次畫的刻度線的坐標不變。
//一秒后重繪 postInvalidateDelayed(1000);
作用是在1000ms(1s)后再次執行View的draw流程,產生指針運動的效果。
感謝各位的閱讀!關于“Android怎么實現簡單時鐘View的方法”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。