为了买彩票,我写了这个控件

作者: a49f87ef5d4f | 来源:发表于2019-03-10 22:03 被阅读1次

0.

最近偶尔会买个双色球,一周买个6块钱的,也不多,就是凑个热闹,为生活添加个小情趣。因为不会选号,每次都是机选,作为一个阴谋论者,我觉得机选可能不够“随机”,为此我决定自己写个程序为我选号,为此我模仿老虎机写了一个控件。先上图

image

1.

先设计一下

1.1支持从数字和数组获取数据

1.2绘制两个数字,当前数字和下一个数字

1.3设置便宜量,并实现加速

1.4开始和停止,停止时添加回调

1.5支持设置文字大小与颜色

2.

废话少说,上代码

package com.skateboard.numberrunningview

import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.support.v4.view.ViewCompat
import android.util.AttributeSet
import android.view.View

class 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

关注我的公众号

相关文章

  • 为了买彩票,我写了这个控件

    0. 最近偶尔会买个双色球,一周买个6块钱的,也不多,就是凑个热闹,为生活添加个小情趣。因为不会选号,每次都是机选...

  • Android程序员用控件玩彩票,告诉网友什么叫真正的随机

    为了买彩票,我写了这个控件 0. 最近偶尔会买个双色球,一周买个6块钱的,也不多,就是凑个热闹,为生活添加个小情趣...

  • 随手拍(第四期)

    第一次买彩票 第一次买彩票不是为了中奖,而是为了体验,一开始不知道这个彩票儿怎么玩儿,进了彩票亭的阿姨只顾着玩儿手...

  • 《 一只不会轻功的猫》之”“为什么买彩票”

    一格 文字:我为什么买彩票? 图:人形猫在彩票售票处 二格 文字:我仔细的想了想这个问题。不全是为了中大奖。因为概...

  • 彩票

    一直喜欢买彩票,这个习惯我坚持了多年了。买彩票就想着万一中个大奖,就可以少奋斗好多年了。这也是很多买彩票的人心中所...

  • 我想:人为什么买彩票呢?买彩票的人,谁不想中奖?不想中奖又何必买彩票,还不如扔了,或者给乞讨者。所以,买彩票的人都...

  • 我对彩票不感冒

    我有个同事,特别喜欢买彩票,多次劝我买上几注,我的答复是,不买,不信,这个是机率,太小。哈! 对于彩票,我认为买了...

  • 2020-07-12

    今天又是咸鱼的一天。。。。然后盘算着下次什么时候买彩票,为了省下买彩票的钱,我自己竟然开始学习做饭了,毕竟以前是抱...

  • 运气不错!哈哈!

    我刚刚去买旁边的彩票点去买彩票了,也就买了40元的彩票而已。玩玩而已,我从来也不买多。绝对不会像那些赌彩票的...

  • 我还在买彩票

    说实话,我喜欢买彩票,那是我心里的一种寄托和自我安慰,给自己一个遥遥无期却真有可能发生的希望。 但我又不迷恋彩票,...

网友评论

    本文标题:为了买彩票,我写了这个控件

    本文链接:https://www.haomeiwen.com/subject/gkxmpqtx.html