自定义贝塞尔曲线仿华为运动健康app睡眠柱状图

打开手机华为运动健康app,观察睡眠详情页数据统计柱状图

码:

class BottomBollView : RelativeLayout{

    private var shadowLength = 6f
    var waveHigh=60f
    private var waveRadio: Float = 60f
    var waveX=-1f
    var waveY=0f
    var waveRadioMultiple =2.0f
    var waveHighPercent =0.8f
    var waveCount =30
    var waveColor=Color.GRAY
    var bollColor:Int=Color.parseColor("#FFDAD6")
    var bollMargin=-1f
    val paint = Paint()
    val path = Path()

    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
    ) {
        background = GradientDrawable().apply { setColor(Color.TRANSPARENT) }
        val ta = context.obtainStyledAttributes(attrs, R.styleable.BottomWaveViewStyle)
        waveHigh = ta.getDimension(R.styleable.BottomWaveViewStyle_waveHigh, 60f)
        waveRadio = ta.getDimension(R.styleable.BottomWaveViewStyle_waveRadio, 60f)
        waveRadioMultiple = ta.getDimension(R.styleable.BottomWaveViewStyle_waveRadioMultiple, 2.0f)
        shadowLength = ta.getDimension(R.styleable.BottomWaveViewStyle_shadowLength, 0f )
        waveCount = ta.getInteger(R.styleable.BottomWaveViewStyle_waveCount, 30 )
        waveHighPercent = ta.getFloat(R.styleable.BottomWaveViewStyle_waveHighPercent, 0.8f )
        waveColor =ta.getColor(R.styleable.BottomWaveViewStyle_waveColor,Color.GRAY)
        bollColor=ta.getColor(R.styleable.BottomWaveViewStyle_bollColor,Color.parseColor("#FFDAD6"))
        bollMargin=ta.getDimension(R.styleable.BottomWaveViewStyle_bollMargin,-1f)
        ta.recycle()
        paint.apply {
            style = Paint.Style.FILL
            color = Color.RED
            maskFilter = null
            isDither=false
            isAntiAlias = true
            setShadowLayer(shadowLength, 0.toFloat(), 0.toFloat(), Color.LTGRAY)

        }
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        var w=measuredWidth
        waveRadio = w .toFloat() / waveCount
        waveHigh = waveRadio * waveHighPercent
        if (bollMargin==-1f){
            bollMargin = waveHigh/3
        }
    }

    @SuppressLint("DrawAllocation")
    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        path.reset()
        paint.color = waveColor
        paint.style=Paint.Style.FILL
        if (waveX == -1f){
            waveX =width /2 .toFloat() -100
        }
        waveY =height.toFloat() - waveHigh * 2
        //左边的半圆
        val rectL = RectF(
            0f,
            0f,
            waveX - waveRadio * waveRadioMultiple ,
            waveY
        )
        path.addRect(rectL,Path.Direction.CCW)

        path.moveTo(waveX- waveRadio*waveRadioMultiple, waveY )
        path.cubicTo(
            waveX - waveRadio,
            waveY  ,
            waveX - waveRadio * 0.8f,
            waveY - waveHigh,
            waveX ,
            waveY - waveHigh

        )
        path.lineTo(waveX -  waveRadio*waveRadioMultiple, 0f)
        path.close()
        path.moveTo(waveX, waveY -waveHigh )
        path.cubicTo(
            waveX + waveRadio * 0.8f,
            waveY - waveHigh ,
            waveX + waveRadio,
            waveY ,
            waveX + waveRadio*waveRadioMultiple,
            waveY ,
        )

        path.lineTo(waveX +  waveRadio*waveRadioMultiple, 0f)
        path.close()

        path.moveTo(waveX -  waveRadio*waveRadioMultiple, 0f )
        path.lineTo(waveX , waveY - waveHigh)
        path.lineTo(waveX +  waveRadio*waveRadioMultiple, 0f)
        path.close()
        val rectR = RectF(
            waveX + waveRadio*waveRadioMultiple,
            0f ,
            width.toFloat(),
            waveY
        )
        path.addRect(rectR,Path.Direction.CCW)
//        path1qq.fillType=Path.FillType.EVEN_ODD
        canvas.drawPath(path, paint)


        paint.color=bollColor
        canvas.drawCircle(waveX,waveY+ bollMargin,waveHigh,paint)

        var hour="12:00"
        var timeCount=6
        paint.textSize=32f
        paint.textAlign=Paint.Align.CENTER
        for ( a in 0 ..   6){
            if (a ==0 || a==6){

            }else{
                var tx=width/timeCount * a.toFloat()
                var txy = waveY - waveHigh -30
                var includView=if ( waveX > tx &&  waveX < (tx + 50)) txy  else waveY - waveHigh
                canvas.drawText(hour,width/timeCount * a.toFloat(),includView,paint)
            }
        }

        paint.style=Paint.Style.FILL
        var line= waveY/2
        paint.color=resources.getColor(R.color.design_default_color_secondary_variant)
        var lineRef=RectF()
        var lineRadio=5f
        for (a in 0 .. 3){
            var dataX=width * (a+1) * 10 / 100 .toFloat()
            lineRef= RectF(dataX,0 + line/2,dataX + lineRadio*(a+1),waveY -line/2)
            canvas.drawRoundRect(lineRef,lineRadio,lineRadio,paint)
        }
        paint.color=resources.getColor(R.color.white)
        lineRef= RectF(waveX,0 + line/3,waveX + lineRadio/3,waveY -line/3)
        canvas.drawOval(lineRef,paint)

    }

    var lastX=0f;
    override fun onTouchEvent(event: MotionEvent?): Boolean {

        when(event?.action){

            MotionEvent.ACTION_DOWN ->{
                waveX=event!!.x
                postInvalidate()
                return true
            }

            MotionEvent.ACTION_MOVE ->{
                waveX=event!!.x
                    lastX = waveX
                    postInvalidate()
                return true
            }

            MotionEvent.ACTION_UP ->{
                waveX=event!!.x
                postInvalidate()
                return true
            }
        }

        return super.onTouchEvent(event)
    }
}

运行测试:七七八八 有点神似

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值