中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Android怎么實現簡單時鐘View的方法

發布時間:2021-04-16 11:39:11 來源:億速云 閱讀:173 作者:小新 欄目:移動開發

這篇文章給大家分享的是有關Android怎么實現簡單時鐘View的方法的內容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。

通過Canvas的平移與旋轉簡化繪圖邏輯是一個非常有用的技巧,下面的時鐘view就是利用這個方法完成的,省去了使用三角函數計算坐標的麻煩。

Android怎么實現簡單時鐘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的方法”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

西城区| 武平县| 抚州市| 竹北市| 钟山县| 华阴市| 宁都县| 龙门县| 彝良县| 类乌齐县| 赤峰市| 蚌埠市| 西城区| 恩施市| 靖宇县| 江门市| 陆良县| 贡觉县| 鲜城| 土默特左旗| 安阳县| 邵东县| 凤凰县| 古丈县| 阳新县| 德兴市| 黎川县| 德惠市| 辉南县| 普定县| 铅山县| 肥城市| 西城区| 临沧市| 桐城市| 怀柔区| 洪雅县| 辽中县| 大邑县| 东乌珠穆沁旗| 北川|