最近在练习自定义view, 想起之前面试的时候笔试有道题是写出自定义一个时钟的关键代码. 今天就来实现一下. 步骤依然是先分析, 再上代码.
上述就是android开发分享Android自定义View实现时钟功能的全部内容,如果对大家有所用处且需要了解更多关于Android学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)
实现效果
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 } }
以上就是android开发分享Android自定义View实现时钟功能的全部内容,希望对大家的学习有所帮助,也希望大家多多支持<计算机技术网>。
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请点击右边联系管理员删除。
如若转载,请注明出处:https://www.ctvol.com/addevelopment/1239401.html