主要通过6个控制点实现。

val startPoint = PointF()
val endPoint = PointF()
val control1 = PointF()
val control2 = PointF()
val control3 = PointF()
val control4 = PointF()

绘制过程:

private fun drawWater(canvas: Canvas) {
waterPath.apply {
reset()
moveTo(startPoint)
cubicTo(control1, control3, endPoint)
cubicTo(control4, control2, startPoint)
}
canvas.save()
// clipOut 出中间的圆
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
canvas.clipOutPath(Path().apply { addCircle(circleX, circleY, circleR, Path.Direction.CW) })
} else {
canvas.clipPath(Path().apply {
addCircle(circleX, circleY, circleR, Path.Direction.CW)
}, Region.Op.DIFFERENCE)
}
canvas.drawPath(waterPath, waterPaint)
canvas.drawCircle(circleX, circleY, circleR, waterPaint)
canvas.restore()
}

一些扩展函数,方便直接使用 PointF。

private fun Path.moveTo(p: PointF) {
moveTo(p.x, p.y)
}
private fun Path.lineTo(p: PointF) {
lineTo(p.x, p.y)
}
private fun Path.cubicTo(control1: PointF, control2: PointF, end: PointF) {
cubicTo(control1.x, control1.y, control2.x, control2.y, end.x, end.y)
}
private fun Path.quadTo(control: PointF, end: PointF) {
quadTo(control.x, control.y, end.x, end.y)
}
private fun Canvas.drawPoint(p: PointF, paint: Paint) {
drawPoint(p.x, p.y, paint)
}

动画

分为 6 个阶段完成

class AnimatorHelper(val target: JumpWater) {

    private var animDuration = 300L
private var animStartDown: ValueAnimator? = null
private var animStartJump: ValueAnimator? = null
private var animJump: ValueAnimator? = null
private var animDown: ValueAnimator? = null
private var animTail: ValueAnimator? = null
private var animTailReconver: ValueAnimator? = null
private var animSet: AnimatorSet? = null internal fun startJump(tailMove: Float, jumpH: Float) {
endJump()
animStartDown = ValueAnimator.ofFloat(0f, jumpH).apply {
addUpdateListener {
target.updateStartDown(it.animatedValue as Float)
}
}
animStartJump = ValueAnimator.ofFloat(jumpH, 0f).apply {
addUpdateListener {
target.updateStartDown(it.animatedValue as Float)
}
}
animJump = ValueAnimator.ofFloat(0f, jumpH).apply {
addUpdateListener {
target.updateJump(it.animatedValue as Float)
}
}
animDown = ValueAnimator.ofFloat(jumpH, 0f).apply {
addUpdateListener {
target.updateJump(it.animatedValue as Float)
}
}
animTail = ValueAnimator.ofFloat(0f, tailMove).apply {
addUpdateListener {
target.updateTail(it.animatedValue as Float)
}
}
animTailReconver = ValueAnimator.ofFloat(tailMove, 0f).apply {
addUpdateListener {
target.updateTail(it.animatedValue as Float)
}
} val tailSet = AnimatorSet().apply {
playTogether(animJump, animTail)
} val tailSetReconver = AnimatorSet().apply {
playTogether(animDown, animTailReconver)
} animSet = AnimatorSet().apply {
playSequentially(animStartDown, animStartJump, tailSet, tailSetReconver)
addListener(object : Animator.AnimatorListener {
override fun onAnimationRepeat(animation: Animator?) { } override fun onAnimationEnd(animation: Animator?) {
mOnAnimEndListener?.onAnimEnd()
} override fun onAnimationCancel(animation: Animator?) {
} override fun onAnimationStart(animation: Animator?) {
}
})
start()
}
}
}

具体请看:https://github.com/stefanJi/AndroidView/tree/master/jumpwater

最新文章

  1. Linux下搭建VPN服务器(CentOS、pptp)转
  2. tableView性能优化
  3. android私有文件夹的访问
  4. 3. NHibernate基础知识 - 你必须知道的一些事情
  5. h.264加权预测
  6. Java程序员面试题集(116-135)
  7. 自制DTU
  8. GridView用法的修改和删除
  9. android圆形进度条ProgressBar颜色设置
  10. git常用命令--转载
  11. initializer element is not a compile-time constant
  12. CSS揭秘—透明边框(一)
  13. 小程序+node+mysql做的小项目
  14. Python(x,y) 的 FTP 下载地址
  15. 没有内涵段子可以刷了,利用Python爬取段友之家贴吧图片和小视频(含源码)
  16. 使用Oracle数据库时的org.springframework.jdbc.BadSqlGrammarException:
  17. 牛客网-《剑指offer》-旋转数组的最小数
  18. Java排序算法——堆排序
  19. 删除对象的属性 delete的用法
  20. mysql索引之哈希索引

热门文章

  1. lua_note_01_lua介绍
  2. ACM蓝桥杯之换硬币问题
  3. 6.3.3 使用 shelve 模块操作二进制文件
  4. Ch’s gift
  5. SCU Travel
  6. ubuntu 14.04 gcc/g++版本降低
  7. 清北学堂模拟赛d1t3 听音乐(music)
  8. 清北学堂模拟赛d6t3 反击数
  9. Groovy简单再入门
  10. N天学习一个linux命令之yum