打开手机华为运动健康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)
}
}
运行测试:七七八八 有点神似