<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
最近在練習自定義view, 想起之前面試的時候筆試有道題是寫出自定義一個時鐘的關鍵程式碼. 今天就來實現一下. 步驟依然是先分析, 再上程式碼.
時鐘主要分為五個部分:
1、中心點: 圓心位置
2、圓盤: 以中心點為圓心,drawCircle畫個圓
3、刻度:
paint有個aip, setPathEffect可以根據path畫特效, 那麼刻度就可以根據圓的path畫一個矩形path的特效, 並且這個api只會畫特效, 不會畫出圓.
/** * shape: 特效的path, 這裡傳一個矩形 * advance: 兩個特效path之間的間距, 即兩個矩形的left間距 * phase: 特效起始位置的偏移 * style: 原始path拐彎的時候特效path的轉換方式,這裡用ROTATE跟著旋轉即可 */ PathDashPathEffect(Path shape, float advance, float phase, Style style)
刻度又分兩種, 粗一點刻度: 3、6、9、12, 和細一點的刻度. 兩種特效又可以用SumPathEffect合起來畫
SumPathEffect(PathEffect first, PathEffect second)
4、時分秒指標
時分秒指標都是一個圓角矩形, 先把他們的位置計算出來, 然後旋轉圓心去繪製不同角度的指標.
5、動畫效果
TimerTask每隔一秒計算時間, 根據時間去換算當前時分秒指標的角度, 動態變數只有三個角度.
// // Created by skylar on 2022/4/19. // class ClockView : View { private var mTimer: Timer? = null private val mCirclePaint: Paint = Paint() private val mPointerPaint: Paint = Paint() private val mTextPaint: Paint = Paint() private val mCirclePath: Path = Path() private val mHourPath: Path = Path() private val mMinutePath: Path = Path() private val mSecondPath: Path = Path() private lateinit var mPathMeasure: PathMeasure private lateinit var mSumPathEffect: SumPathEffect private var mViewWidth = 0 private var mViewHeight = 0 private var mCircleWidth = 6f private var mRadius = 0f private var mRectRadius = 20f private var mHoursDegree = 0f private var mMinutesDegree = 0f private var mSecondsDegree = 0f private var mCurrentTimeInSecond = 0L constructor(context: Context) : super(context) constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0) constructor( context: Context, attrs: AttributeSet?, defStyleAttr: Int ) : super(context, attrs, defStyleAttr) init { mCirclePaint.color = Color.BLACK mCirclePaint.isAntiAlias = true mCirclePaint.style = Paint.Style.STROKE mCirclePaint.strokeWidth = mCircleWidth mPointerPaint.color = Color.BLACK mPointerPaint.isAntiAlias = true mPointerPaint.style = Paint.Style.FILL mTextPaint.color = Color.BLACK mTextPaint.isAntiAlias = true mTextPaint.style = Paint.Style.FILL mTextPaint.textSize = 40f } override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) { super.onSizeChanged(w, h, oldw, oldh) mViewWidth = measuredWidth - paddingLeft - paddingRight mViewHeight = measuredHeight - paddingTop - paddingBottom mRadius = mViewWidth / 2 - mCircleWidth mCirclePath.addCircle(0f, 0f, mRadius, Path.Direction.CW) mPathMeasure = PathMeasure(mCirclePath, false) val minutesShapePath = Path() val quarterShapePath = Path() minutesShapePath.addRect(0f, 0f, mRadius * 0.01f, mRadius * 0.06f, Path.Direction.CW) quarterShapePath.addRect(0f, 0f, mRadius * 0.02f, mRadius * 0.06f, Path.Direction.CW) val minutesDashPathEffect = PathDashPathEffect( minutesShapePath, mPathMeasure.length / 60, 0f, PathDashPathEffect.Style.ROTATE ) val quarterDashPathEffect = PathDashPathEffect( quarterShapePath, mPathMeasure.length / 12, 0f, PathDashPathEffect.Style.ROTATE ) mSumPathEffect = SumPathEffect(minutesDashPathEffect, quarterDashPathEffect) val hourPointerHeight = mRadius * 0.5f val hourPointerWidth = mRadius * 0.07f val hourRect = RectF( -hourPointerWidth / 2, -hourPointerHeight * 0.7f, hourPointerWidth / 2, hourPointerHeight * 0.3f ) mHourPath.addRoundRect(hourRect, mRectRadius, mRectRadius, Path.Direction.CW) val minutePointerHeight = mRadius * 0.7f val minutePointerWidth = mRadius * 0.05f val minuteRect = RectF( -minutePointerWidth / 2, -minutePointerHeight * 0.8f, minutePointerWidth / 2, minutePointerHeight * 0.2f ) mMinutePath.addRoundRect(minuteRect, mRectRadius, mRectRadius, Path.Direction.CW) val secondPointerHeight = mRadius * 0.9f val secondPointerWidth = mRadius * 0.03f val secondRect = RectF( -secondPointerWidth / 2, -secondPointerHeight * 0.8f, secondPointerWidth / 2, secondPointerHeight * 0.2f ) mSecondPath.addRoundRect(secondRect, mRectRadius, mRectRadius, Path.Direction.CW) startAnimator() } override fun onDraw(canvas: Canvas?) { super.onDraw(canvas) if (canvas == null) { return } canvas.translate((mViewWidth / 2).toFloat(), (mViewHeight / 2).toFloat()) //畫圓盤 mCirclePaint.pathEffect = null canvas.drawPath(mCirclePath, mCirclePaint) //畫刻度 mCirclePaint.pathEffect = mSumPathEffect canvas.drawPath(mCirclePath, mCirclePaint) //時分秒指標 mPointerPaint.color = Color.BLACK canvas.save() canvas.rotate(mHoursDegree) canvas.drawPath(mHourPath, mPointerPaint) canvas.restore() canvas.save() canvas.rotate(mMinutesDegree) canvas.drawPath(mMinutePath, mPointerPaint) canvas.restore() canvas.save() canvas.rotate(mSecondsDegree) canvas.drawPath(mSecondPath, mPointerPaint) canvas.restore() //畫中心點 mPointerPaint.color = Color.WHITE canvas.drawCircle(0f, 0f, mRadius * 0.02f, mPointerPaint) } private fun startAnimator() { val cal = Calendar.getInstance() val hour = cal.get(Calendar.HOUR) //小時 val minute = cal.get(Calendar.MINUTE) //分 val second = cal.get(Calendar.SECOND) //秒 mCurrentTimeInSecond = (hour * 60 * 60 + minute * 60 + second).toLong() if (mTimer == null) { mTimer = Timer() } else { mTimer?.cancel() mTimerTask.cancel() } mTimer?.schedule(mTimerTask, 0, 1000) } private var mTimerTask: TimerTask = object : TimerTask() { override fun run() { mCurrentTimeInSecond++ computeDegree() invalidate() } } //12小時 00:00:00 ~ 12:00:00 private fun computeDegree() { val secondsInOneRoll = 12 * 60 * 60 val currentSeconds = mCurrentTimeInSecond % secondsInOneRoll var leftSeconds = currentSeconds val hours = currentSeconds / 60 / 60 leftSeconds = currentSeconds - hours * 60 * 60 val minutes = leftSeconds / 60 leftSeconds -= minutes * 60 val seconds = leftSeconds % 60 mHoursDegree = hours * 30f mMinutesDegree = minutes * 6f mSecondsDegree = seconds * 6f } }
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援it145.com。
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45