Android——贝塞尔曲线的水波浪效果实现
Posted 化作孤岛的瓜
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android——贝塞尔曲线的水波浪效果实现相关的知识,希望对你有一定的参考价值。
使用贝塞尔曲线实现的水波浪效果,在很多杀毒软件的进度条显示中都有应用:
这个效果呢以前在有一个项目中需要实现过,当时是使用的正弦曲线做的效果,不过后来发现贝塞尔曲线也可以做出相同的效果,并且代码更为优雅。
那么对于初学者来说呢,首先需要了解什么是贝塞尔曲线,网上有很多教程,这里我找到了比较容易看懂的博客:
我们常用的是二阶贝塞尔曲线,其推导公式为:
但是在android中,Path类提供了qudto方法去绘制一段贝塞尔曲线,因此,只要知道3个点就可以绘制出一段贝塞尔曲线,只需要6个点就可以模拟出正弦波浪曲线。
实现思路:
1.首先大体上需要绘制两段横版S型曲线,然后使用动画效果不断左平移来实现波浪的滑动效果。
2.每一段S型曲线需要确定5个点的位置:
其中对应两段贝塞尔曲线,即P1-P3,P3-P5
3.绘制过程为首先new一个path,将path移动到P1点,然后计算P2,P3的坐标,通过path的rQuadTo(float dx1, float dy1, float dx2, float dy2)方法绘制出P1-P3的贝塞尔曲线,以此类推绘制P3-P5以及之后的另外两条贝塞尔曲线。
实现代码:
class WaveView : View
private var color: Int
private var paint: Paint
private var path: Path
private var mWidth: Int = 0
private var mHeight: Int = 0
private var cX: Float = 0f
private var cY: Float = 0f
private var xOffset = 0f
private var progress = 50
private val clipPath: Path
private var left: Float = 0f
private var top: Float = 0f
private var right: Float = 0f
private var bottom: Float = 0f
private var xOffsetAnimator: ValueAnimator? = null
fun startAnima()
if (xOffsetAnimator == null)
xOffsetAnimator = ValueAnimator.ofInt(0, width)
xOffsetAnimator?.addUpdateListener animation ->
val value = animation.animatedValue as Int
xOffset = (-value).toFloat()
postInvalidate()
xOffsetAnimator?.interpolator = LinearInterpolator()
xOffsetAnimator?.duration = 1500
xOffsetAnimator?.repeatCount = ValueAnimator.INFINITE
LogUtils.d("开始动画")
xOffsetAnimator?.start()
constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
val array = context?.obtainStyledAttributes(attrs, R.styleable.WaveView)
this.color = array!!.getColor(R.styleable.WaveView_WaveView_color, Color.BLUE)
paint = Paint()
path = Path()
paint.color = this.color;
clipPath = Path()
array.recycle()
override fun onDraw(canvas: Canvas?)
super.onDraw(canvas)
val dx = mWidth / 4f
val dy = mHeight / 8f
val yOffset = (100 - progress) / 100f * height
val p1 = floatArrayOf(xOffset, yOffset)
val p2 = floatArrayOf(dx, -dy)
val p3 = floatArrayOf(2 * dx, 0f)
val p4 = floatArrayOf(dx, dy)
val p5 = floatArrayOf(2 * dx, 0f)
val p6 = floatArrayOf(dx, -dy)
val p7 = floatArrayOf(2 * dx, 0f)
val p8 = floatArrayOf(dx, dy)
val p9 = floatArrayOf(2 * dx, 0f)
paint.style = Paint.Style.FILL
path.reset()
path.moveTo(p1[0], p1[1])
path.rQuadTo(p2[0], p2[1], p3[0], p3[1])
path.rQuadTo(p4[0], p4[1], p5[0], p5[1])
path.rQuadTo(p6[0], p6[1], p7[0], p7[1])
path.rQuadTo(p8[0], p8[1], p9[0], p9[1])
path.lineTo(width.toFloat(), height.toFloat())
path.lineTo(0f, height.toFloat())
path.close()
clipPath.reset()
left = 0f
top = 0f
right = mWidth.toFloat()
bottom = height.toFloat()
clipPath.addArc(left, top, right, bottom, 0f, 360f)
// canvas!!.clipPath(clipPath)
canvas!!.drawPath(path, paint)
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int)
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
mWidth = measuredWidth
mHeight = measuredHeight
cX = (mWidth / 2).toFloat()
cY = (mHeight / 2).toFloat()
Github项目地址:
https://github.com/jiangzhengnan/UI
最近会把实现的UI效果都集中到一个库里面,求start~
以上是关于Android——贝塞尔曲线的水波浪效果实现的主要内容,如果未能解决你的问题,请参考以下文章
Android 高级UI解密 :花式玩转贝塞尔曲线(波浪轨迹变换动画)