欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

android中怎么通過自定義view實現(xiàn)鐘表效果

今天就跟大家聊聊有關(guān)android中怎么通過自定義view實現(xiàn)鐘表效果,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。

成都創(chuàng)新互聯(lián)公司客戶idc服務(wù)中心,提供四川雅安服務(wù)器托管、成都服務(wù)器、成都主機托管、成都雙線服務(wù)器等業(yè)務(wù)的一站式服務(wù)。通過各地的服務(wù)中心,我們向成都用戶提供優(yōu)質(zhì)廉價的產(chǎn)品以及開放、透明、穩(wěn)定、高性價比的服務(wù),資深網(wǎng)絡(luò)工程師在機房提供7*24小時標準級技術(shù)保障。

先看效果圖:

自定義view大家肯定已經(jīng)不陌生了,所以直接今天直接步入正題:如何利用canvas去繪制出一個鐘表

當(dāng)然繪制之前我們必須進行測量(重寫onMeasure),根據(jù)自己的規(guī)則去測量,這暫時是將控件限制為一個正方形。

首先我們先把鐘表分解,看它由哪幾部分組成。如上圖:鐘表包括表盤(刻度)和表針還有文字構(gòu)成。

分清結(jié)構(gòu)之后我們再明確canvas需要畫什么,表盤的構(gòu)成其實就是外層一個圓,然后上面是有規(guī)律的線段,表針就是三個長短不一的線段,再加上12個鐘點文字。這樣一分析是不是發(fā)現(xiàn)調(diào)用canvas的drawCircle、drawLine和drawText就可以完成鐘表的繪制了。

既然明確了我們繪制所需要的方法,那么就開始重頭戲了,告訴canvas在哪繪制這些零件。

最外層的圓是最簡單的,我們只需要以控件的中心為圓心,控件的寬度一半為半徑畫一個圓就可以了。

接下來就是難點一了,這些刻度怎么辦呢,其實我們不難發(fā)現(xiàn)其中的規(guī)律,每個刻度之間的弧度是一樣的,那這樣我們是不是可以通過旋轉(zhuǎn)畫布就可以實現(xiàn)這些刻度的繪制呢,答案是肯定的。

難點二,文字又該如何繪制,難道也通過旋轉(zhuǎn)畫布嗎,但是你想一下,假如通過旋轉(zhuǎn)畫布去繪制文字,那有些文字可是會顛倒的,這并不是我們想要的結(jié)果,那該怎么辦,這時候我們只能通過數(shù)學(xué)計算老老實實的計算每個文字的起始坐標,這些坐標并沒有想象中的復(fù)雜,我們可以根據(jù)中心點的位置和偏移角度(當(dāng)然還需要考慮文字的寬度)算出。

難點三,繪制表針,其實文字繪制出來,那么同樣可以根據(jù)中心點和偏移角度算出表針的起始坐標和結(jié)束坐標表心就是一個實體的圓,這個就簡單了。

好像還沒說時分秒是怎么確定的,這當(dāng)然是通過系統(tǒng)時間獲取的了。說到這里似乎一個靜態(tài)鐘表已經(jīng)繪制出來了,接下來讓它動起來就可以了。在這我們啟動一個線程,讓它隔一秒鐘進行一次重繪即可。

下面我直接貼一下代碼把,代碼是用kotlin實現(xiàn)(這不是重點)的

package com.example.commonui.widgetimport android.annotation.SuppressLintimport android.content.Contextimport android.graphics.Canvasimport android.graphics.Colorimport android.graphics.Paintimport android.os.Handlerimport android.os.Messageimport android.util.AttributeSetimport android.view.Viewimport java.util.*/** * Created by zhang on 2017/12/20. */class ClockView(context: Context?, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : View(context, attrs, defStyleAttr) {  companion object {    private const val DEFAULT_WIDTH = 200 //默認寬度  }  private lateinit var mBlackPaint: Paint//黑色畫筆  private lateinit var mRedPaint: Paint //紅色畫筆  private lateinit var mBlackPaint2: Paint//黑色畫筆  private lateinit var mTextPaint: Paint  private var hour: Int? = null  private var minute: Int? = null  private var second: Int? = null  private val textArray = arrayOf("12", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11")  private var refreshThread: Thread? = null  private var mHandler = @SuppressLint("HandlerLeak")  object : Handler() {    override fun handleMessage(msg: Message?) {      super.handleMessage(msg)      when (msg?.what) {        0 -> {          invalidate()        }      }    }  }  init {    initPaints()  }  /**   * 初始化畫筆   */  private fun initPaints() {    mBlackPaint = Paint()    with(mBlackPaint) {      color = Color.BLACK      strokeWidth = 5f      isAntiAlias = true      style = Paint.Style.STROKE    }    //用于畫表心    mBlackPaint2 = Paint()    with(mBlackPaint2) {      color = Color.BLACK      isAntiAlias = true      style = Paint.Style.FILL    }    mRedPaint = Paint()    with(mRedPaint) {      color = Color.RED      strokeWidth = 5f      isAntiAlias = true    }    mTextPaint = Paint()    with(mTextPaint) {      color = Color.BLACK      textSize = 30f      isAntiAlias = true    }  }  override fun onDraw(canvas: Canvas?) {    super.onDraw(canvas)    //獲取當(dāng)前時間    getCurrentTime()    //先畫最外層的圓圈    drawOuterCircle(canvas)    //畫刻度    drawScale(canvas)    //繪制文字    drawTimeText(canvas)    //繪制表針    drawHand(canvas)    //繪制表心    drawCenter(canvas)  }  private fun getCurrentTime() {    val calendar = Calendar.getInstance()    hour = calendar.get(Calendar.HOUR)    minute = calendar.get(Calendar.MINUTE)    second = calendar.get(Calendar.SECOND)  }  private fun drawOuterCircle(canvas: Canvas?) {    mBlackPaint.strokeWidth = 5f    canvas?.drawCircle(measuredWidth / 2.toFloat(), measuredHeight / 2.toFloat(), (measuredWidth / 2 - 5).toFloat(), mBlackPaint)  }  private fun drawCenter(canvas: Canvas?) {    canvas?.drawCircle(measuredWidth / 2.toFloat(), measuredHeight / 2.toFloat(), 20f, mBlackPaint2)  }  private fun drawHand(canvas: Canvas?) {    drawSecond(canvas, mRedPaint)    mBlackPaint.strokeWidth = 10f    drawMinute(canvas, mBlackPaint)    mBlackPaint.strokeWidth = 15f    drawHour(canvas, mBlackPaint)  }  private fun drawTimeText(canvas: Canvas?) {    val textR = (measuredWidth / 2 - 50).toFloat()//文字構(gòu)成的圓的半徑    for (i in 0..11) {      //繪制文字的起始坐標      val startX = (measuredWidth / 2 + textR * Math.sin(Math.PI / 6 * i) - mTextPaint.measureText(textArray[i]) / 2).toFloat()      val startY = (measuredHeight / 2 - textR * Math.cos(Math.PI / 6 * i) + mTextPaint.measureText(textArray[i]) / 2).toFloat()      canvas?.drawText(textArray[i], startX, startY, mTextPaint)    }  }  private fun drawScale(canvas: Canvas?) {    var scaleLength: Float?    canvas?.save()    //0..59代表[0,59]    for (i in 0..59) {      if (i % 5 == 0) {        //大刻度        mBlackPaint.strokeWidth = 5f        scaleLength = 20f      } else {        //小刻度        mBlackPaint.strokeWidth = 3f        scaleLength = 10f      }      canvas?.drawLine(measuredWidth / 2.toFloat(), 5f, measuredWidth / 2.toFloat(), (5 + scaleLength), mBlackPaint)      canvas?.rotate(360 / 60.toFloat(), measuredWidth / 2.toFloat(), measuredHeight / 2.toFloat())    }    //恢復(fù)原來狀態(tài)    canvas?.restore()  }  /**   * 繪制秒針   */  private fun drawSecond(canvas: Canvas?, paint: Paint?) {    //秒針長半徑 (表針會穿過表心 所以需要根據(jù)兩個半徑計算起始和結(jié)束半徑)    val longR = measuredWidth / 2 - 60    val shortR = 60    val startX = (measuredWidth / 2 - shortR * Math.sin(second!!.times(Math.PI / 30))).toFloat()    val startY = (measuredWidth / 2 + shortR * Math.cos(second!!.times(Math.PI / 30))).toFloat()    val endX = (measuredWidth / 2 + longR * Math.sin(second!!.times(Math.PI / 30))).toFloat()    val endY = (measuredWidth / 2 - longR * Math.cos(second!!.times(Math.PI / 30))).toFloat()    canvas?.drawLine(startX, startY, endX, endY, paint)  }  /**   * 繪制分針   */  private fun drawMinute(canvas: Canvas?, paint: Paint?) {    //半徑比秒針小一點    val longR = measuredWidth / 2 - 90    val shortR = 50    val startX = (measuredWidth / 2 - shortR * Math.sin(minute!!.times(Math.PI / 30))).toFloat()    val startY = (measuredWidth / 2 + shortR * Math.cos(minute!!.times(Math.PI / 30))).toFloat()    val endX = (measuredWidth / 2 + longR * Math.sin(minute!!.times(Math.PI / 30))).toFloat()    val endY = (measuredWidth / 2 - longR * Math.cos(minute!!.times(Math.PI / 30))).toFloat()    canvas?.drawLine(startX, startY, endX, endY, paint)  }  /**   * 繪制時針   */  private fun drawHour(canvas: Canvas?, paint: Paint?) {    //半徑比秒針小一點    val longR = measuredWidth / 2 - 120    val shortR = 40    val startX = (measuredWidth / 2 - shortR * Math.sin(hour!!.times(Math.PI / 6))).toFloat()    val startY = (measuredWidth / 2 + shortR * Math.cos(hour!!.times(Math.PI / 6))).toFloat()    val endX = (measuredWidth / 2 + longR * Math.sin(hour!!.times(Math.PI / 6))).toFloat()    val endY = (measuredWidth / 2 - longR * Math.cos(hour!!.times(Math.PI / 6))).toFloat()    canvas?.drawLine(startX, startY, endX, endY, paint)  }  /**   * 進行測量   */  override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {    super.onMeasure(widthMeasureSpec, heightMeasureSpec)    val widthSpecMode = MeasureSpec.getMode(widthMeasureSpec)    val widthSpecSize = MeasureSpec.getSize(widthMeasureSpec)    val heightSpecMode = MeasureSpec.getMode(heightMeasureSpec)    val heightSpecSize = MeasureSpec.getSize(heightMeasureSpec)    val result = if (widthSpecMode == MeasureSpec.AT_MOST && heightSpecMode == MeasureSpec.AT_MOST) {      DEFAULT_WIDTH    } else {      Math.min(widthSpecSize, heightSpecSize)    }    setMeasuredDimension(result, result)  }  override fun onAttachedToWindow() {    super.onAttachedToWindow()    //啟動線程 刷新界面    refreshThread = Thread(Runnable {      while (true) {        try {          Thread.sleep(1000)          mHandler.sendEmptyMessage(0)        } catch (e: InterruptedException) {          break        }      }    })    refreshThread?.start()  }  override fun onDetachedFromWindow() {    super.onDetachedFromWindow()    mHandler.removeCallbacksAndMessages(null)    //中斷線程    refreshThread?.interrupt()  }}

看完上述內(nèi)容,你們對android中怎么通過自定義view實現(xiàn)鐘表效果有進一步的了解嗎?如果還想了解更多知識或者相關(guān)內(nèi)容,請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝大家的支持。

文章題目:android中怎么通過自定義view實現(xiàn)鐘表效果
本文網(wǎng)址:http://www.chinadenli.net/article36/ieoesg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供外貿(mào)建站虛擬主機品牌網(wǎng)站設(shè)計網(wǎng)站內(nèi)鏈網(wǎng)站排名小程序開發(fā)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

成都網(wǎng)站建設(shè)