主要通过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

Android贝塞尔曲线应用-跳动的水滴的更多相关文章

  1. Android 贝塞尔曲线 折线图

    1.贝塞尔曲线:http://baike.baidu.com/view/60154.htm,在这里理解什么是贝塞尔曲线 2.直接上图: 3.100多行代码就可以画出贝塞尔曲线,直接上代码 packag ...

  2. Android -- 贝塞尔曲线公式的推导

    1,最近看了几个不错的自定义view,发现里面都会涉及到贝塞尔曲线知识,深刻的了解到贝塞尔曲线是进阶自定义view的一座大山,so,今天先和大家来了解了解. 2,贝塞尔曲线作用十分广泛,简单举几个的栗 ...

  3. Android -- 贝塞尔曲线公式的推导和简单使用

    1,最近看了几个不错的自定义view,发现里面都会涉及到贝塞尔曲线知识,深刻的了解到贝塞尔曲线是进阶自定义view的一座大山,so,今天先和大家来了解了解. 2,贝塞尔曲线作用十分广泛,简单举几个的栗 ...

  4. Android 贝塞尔曲线解析

    相信很多同学都知道"贝塞尔曲线"这个词,我们在很多地方都能经常看到.利用"贝塞尔曲线"可以做出很多好看的UI效果,本篇博客就让我们一起学习"贝塞尔曲线 ...

  5. Android 贝塞尔曲线的浅析

    博客也开了挺长时间了,一直都没有来写博客,主要原因是自己懒---此篇博客算是给2017年一个好的开始,同时也给2016年画上一个句点,不留遗憾. 那就让我们正式进入今天的主题:贝塞尔曲线. 首先,让我 ...

  6. Android 贝塞尔曲线库

    最近做的一个小项目需要绘制一些折线图,AChartEngine其实里面包含很多图,虽然是开源的,但毕竟不是自己写的,而且项目稍有点庞大,有些东西修改起来还是得花点时间的,所以最后打算自己写一个,参考了 ...

  7. Android 贝塞尔曲线

    博客图片备份位置:

  8. Android中贝塞尔曲线的绘制方法

    贝塞尔曲线,很多人可能不太了解,什么叫做贝塞尔曲线呢?这里先做一下简单介绍:贝塞尔曲线也可以叫做贝济埃曲线或者贝兹曲线,它由线段与节点组成,节点是可拖动的支点,线段像可伸缩的皮筋.一般的矢量图形软件常 ...

  9. android 利用Path.cubicTo 画 贝塞尔曲线

    Path.cubicTo void android.graphics.Path.cubicTo(float x1, float y1, float x2, float y2, float x3, fl ...

随机推荐

  1. Entity Framework Connection String不保留密码的方法

    添加Entity Data Model的时候,到最后一步,有两个radio box: 如果选择include sensitive data,虽然很方便,但是在web.config或者app.confi ...

  2. 清北学堂模拟赛d4t5 b

    分析:一眼树形dp题,就是不会写QAQ.树形dp嘛,定义状态肯定有一维是以i为根的子树,其实这道题只需要这一维就可以了.设f[i]为以i为根的子树中的权值和.先处理子树内部的情况,用一个数组son[i ...

  3. 清北学堂模拟赛d3t3 c

    分析:一开始拿到这道题真的是无从下手,暴力都很难打出来.但是基本的方向还是要有的,题目问的是方案数,dp不行就考虑数学方法.接下来比较难想.其实对于每一行或者每一列,我们任意打乱顺序其实对答案是没有影 ...

  4. hdu 1569 最大权独立集

    /*最大点权独立集=sum-最小点权覆盖*/ #include<stdio.h> #include<string.h> #include<queue> using ...

  5. github的submodel错误

    原文地址 简要:直接把github上的仓库删除重建,本地的仓库也删除重建,再重新上传就OK了 最近想整理一下工作室官网的东西,那是一个用github pages写的网站,在上传一些post文章的时候, ...

  6. cogs 7. 通信线路

    7. 通信线路 ★★   输入文件:mcst.in   输出文件:mcst.out   简单对比时间限制:1.5 s   内存限制:128 MB 问题描述 假设要在n个城市之间建立通信联络网,则连通n ...

  7. Findbug插件静态java代码扫描工具使用

    本文转自http://blog.csdn.net/gaofuqi/article/details/22679609 感谢作者 FindBugs 是由马里兰大学提供的一款开源 Java静态代码分析工具. ...

  8. 2015 测试赛 同构 hihoCoder

    题目1 : 同构 时间限制:2000ms 单点时限:1000ms 内存限制:256MB 描述 给定2个树A和B,保证A的节点个数>=B的节点个数. 现在你需要对树A的边进行二染色. 一个好的染色 ...

  9. 基于QT的多线程server

    // thread.cpp #include "thread.h" Thread::Thread(int socketDescriptor, QObject *parent) : ...

  10. poj3296--Rinse(三分)

    题目链接:点击打开链接 题目大意:有一个酒桶容量为Vc.里面还有Vw的酒,如今用Vb的水去刷酒桶,每次酒桶的内壁上会留下Vr的液体,最多能够刷k次,问怎么样刷酒桶.能够让酒桶里面的就最少. 假设Vb+ ...