使用贝塞尔曲线实现的水波浪效果,在很多杀毒软件的进度条显示中都有应用:

这个效果呢以前在有一个项目中需要实现过,当时是使用的正弦曲线做的效果,不过后来发现贝塞尔曲线也可以做出相同的效果,并且代码更为优雅。

那么对于初学者来说呢,首先需要了解什么是贝塞尔曲线,网上有很多教程,这里我找到了比较容易看懂的博客:

贝塞尔曲线原理(实现图真漂亮)

我们常用的是二阶贝塞尔曲线,其推导公式为:

但是在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~

更多相关文章

  1. android canvas常用的方法解析(一)
  2. 将JavaFX运行到Android上
  3. Android绘图机制(二)--2D绘图基础
  4. android 震动效果类
  5. Android(安卓)多个输入框的自动跳转
  6. 成佩涛编程之路——Android控件动画效果(二)
  7. Android(安卓)弹无虚发之第三弹:ActionBar 更换背景、颜色、文字,
  8. Android自动手绘,圆你儿时画家梦!
  9. Android模拟键盘输入功能的实现

随机推荐

  1. BadgeView 与 RadioButton
  2. Android 设备管理器和有权查看使用情况的
  3. Android 软键盘盖住输入框的问题
  4. android 手机滤镜
  5. android HorizontalScrollView实现滚动监
  6. android自定义属性之format介绍
  7. Android - Jar mismatch! Fix your depen
  8. ListView.setOnItemClickListener 点击无
  9. Android(安卓)8.0 系统启动流程之init进
  10. android 完美退出所有Activity的demo