为了买彩票,我写了这个控件
0.
最近偶尔会买个双色球,一周买个6块钱的,也不多,就是凑个热闹,为生活增加个小情趣。由于不会选号,每次都是机选,作为一个阴谋论者,我觉得机选可能不够“随机”,为此我决定自己写个程序为我选号,为此我模仿老虎机写了一个控件。先上图
image
1.
先设计一下
1.1支持从数字和数组获取数据
1.2绘制两个数字,当前数字和下一个数字
1.3设置便宜量,并实现加速
1.4开始和中止,中止时增加回调
1.5支持设置文字大小与颜色
2.
废话少说,上代码
package com.skateboard.numberrunningviewimport android.content.Contextimport android.graphics.Canvasimport android.graphics.Colorimport android.graphics.Paintimport android.support.v4.view.ViewCompatimport android.util.AttributeSetimport android.view.Viewclass NumberRunningView(context: Context, attributes: AttributeSet?) : View(context, attributes) { private var numberColor = Color.WHITE private var numberSize = 15.0f //开始时的数字或者者数组下标 var min = 0 //最大的数字或者者数组下标 var max = 0 //当前要绘制数字或者者数组下标 private var now = min //每次刷新移动的距离 private var offset = 0 private var paint = Paint(Paint.ANTI_ALIAS_FLAG) private var isStart = false var maxSpeed = 10f //当前移动速度 private var curSpeed = 0f //加速度增量 private var speedOffset = 0.1f var dataList: List<Int>? = null set(value) { field = value min = 0 max = (value?.size ?: 1) - 1 now = min offset = 0 } var onNumberSelectedListener: OnNumberSelectedListenern? = null init { if (attributes != null) { parseAttrs(attributes) } initPaint() } constructor(context: Context) : this(context, null) private fun parseAttrs(attributes: AttributeSet) { val typedArray = context.obtainStyledAttributes(attributes, R.styleable.NumberRunningView) min = typedArray.getInt(R.styleable.NumberRunningView_min, min) max = typedArray.getInt(R.styleable.NumberRunningView_max, max) maxSpeed = typedArray.getFloat(R.styleable.NumberRunningView_maxSpeed, maxSpeed) numberColor = typedArray.getColor(R.styleable.NumberRunningView_numberColor, numberColor) numberSize = typedArray.getDimension(R.styleable.NumberRunningView_numberSize, numberSize) speedOffset = typedArray.getFloat(R.styleable.NumberRunningView_speedOffset, 0.1f) typedArray.recycle() now = min } private fun initPaint() { paint.textSize = numberSize paint.color = numberColor } override fun onDraw(canvas: Canvas?) { super.onDraw(canvas) canvas?.let { drawNow(it) drawNext(it) calCurSpeed() calOffset() } } private fun calCurSpeed() { curSpeed += speedOffset if (curSpeed > maxSpeed) curSpeed = maxSpeed } private fun drawNow(canvas: Canvas) { val curDataList = dataList var nowNum = "0" nowNum = if (curDataList != null) { curDataList[now].toString() } else { now.toString() } val numWidth = paint.measureText(nowNum) canvas.drawText(nowNum, width / 2 - numWidth / 2, height / 2 - offset + paint.textSize / 2, paint) } private fun drawNext(canvas: Canvas) { val curDataList = dataList var nextNum = "" if (curDataList == null) { nextNum = if (now + 1 > max) { min.toString() } else { (now + 1).toString() } } else { nextNum = if (now + 1 > max) { curDataList[min].toString() } else { (curDataList[now + 1]).toString() } } val numWidth = paint.measureText(nextNum) canvas.drawText(nextNum, width / 2 - numWidth / 2, 1.5f * height - offset + paint.textSize / 2, paint) } private fun calOffset() { if (isStart) { if (offset == height) { offset = 0 if (now + 1 > max) { now = min } else { now += 1 } } else if (offset + curSpeed > height) { offset = height } else { offset = (offset + curSpeed).toInt() } postInvalidate() } else { if (offset != 0 && offset != height) { offset = if (offset + curSpeed > height) { height } else { (offset + curSpeed).toInt() } postInvalidate() } else { if (offset == 0) { val curDataList = dataList if (curDataList != null) { onNumberSelectedListener?.onNumberSelected(curDataList[now]) } else { onNumberSelectedListener?.onNumberSelected(now) } } else { val curDataList = dataList if (curDataList != null) { onNumberSelectedListener?.onNumberSelected(if (now == max) curDataList[min] else curDataList[now + 1]) } else { onNumberSelectedListener?.onNumberSelected(if (now == max) min else now + 1) } } } } } fun start() { if (isStart) { return } curSpeed = 0f isStart = true if (ViewCompat.isAttachedToWindow(this)) { postInvalidate() } } fun stop() { isStart = false } interface OnNumberSelectedListenern { fun onNumberSelected(num: Int) }}
代码比较简单,没什么难度,先看onDraw方法
override fun onDraw(canvas: Canvas?) { super.onDraw(canvas) canvas?.let { drawNow(it) drawNext(it) calCurSpeed() calOffset() } }
绘制当前数字,绘制下一个数字,计算当前速度,计算偏移量,这个速度主要是用来看起来开始时数字的翻转有一个加速的过程。看一下drawNow方法
private fun drawNow(canvas: Canvas) { val curDataList = dataList var nowNum = "0" nowNum = if (curDataList != null) { curDataList[now].toString() } else { now.toString() } val numWidth = paint.measureText(nowNum) canvas.drawText(nowNum, width / 2 - numWidth / 2, height / 2 - offset + paint.textSize / 2, paint) }
首先根据数据源的不同获取的数据,而后计算文字绘制的位置,而后绘制
drawNext大同小异,无非就是一个下一个数字的判断问题
calOffset方法
private fun calOffset() { if (isStart) { if (offset == height) { offset = 0 if (now + 1 > max) { now = min } else { now += 1 } } else if (offset + curSpeed > height) { offset = height } else { offset = (offset + curSpeed).toInt() } postInvalidate() } else { if (offset != 0 && offset != height) { offset = if (offset + curSpeed > height) { height } else { (offset + curSpeed).toInt() } postInvalidate() } else { if (offset == 0) { val curDataList = dataList if (curDataList != null) { onNumberSelectedListener?.onNumberSelected(curDataList[now]) } else { onNumberSelectedListener?.onNumberSelected(now) } } else { val curDataList = dataList if (curDataList != null) { onNumberSelectedListener?.onNumberSelected(if (now == max) curDataList[min] else curDataList[now + 1]) } else { onNumberSelectedListener?.onNumberSelected(if (now == max) min else now + 1) } } } } }
假如处于运行状态,先判断控件当前偏移量,假如等于控件高度,那么就重置为0,而后将now置为下一个数,否则就加上速度重新计算偏移量。假如不处于运行状态,那么判断当前的偏移量,假如既不等于0也不等于控件高度,说明处于一个中间状态,那么就让它移到下一个位置,并调用回调函数。其余的也没什么关键了,各位有需要的看代码就好了
3.
github
image
关注我的公众号
说明
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » 为了买彩票,我写了这个控件
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » 为了买彩票,我写了这个控件