主要通过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. Google Cloud SSH 连接配置

    设置当前用户及root用户的密码 sudo passwd xx-user # 输入新密码 sudo passwd root # 输入新密码(建议保持一样) 在本地生成私钥和公钥 cd ~/.ssh s ...

  2. 《hello-world》第八次团队作业:Alpha冲刺-Scrum Meeting 2

    项目 内容 这个作业属于哪个课程 2016级计算机科学与工程学院软件工程(西北师范大学) 这个作业的要求在哪里 实验十二 团队作业8:软件测试与Alpha冲刺 团队名称 <hello--worl ...

  3. 个人学习记录--取表中Name相同的最大值,非Group By,可延伸

    ), qy ), je INT); INSERT INTO @t SELECT '产品一', '北京', UNION ALL SELECT '产品一', '上海', UNION ALL SELECT ...

  4. linux修改mysql表结构

    增加字段: alter table [tablename] add [字段名] [字段类型] first(首位); alter table [tablename] add [字段名] [字段类型] a ...

  5. 创建序列化器,序列化管理器,closureSerializer

    创建序列化器,序列化管理器,closureSerializer //通过反射创建序列化对象 // Create an instance of the class with the given name ...

  6. [Codeforces 872]比赛记录

    强行打了$cf$上的第一场比赛,现在感觉自己的$rating$会炸飞= = A  这是练习输入输出吗QAQ,竟然$WA$了两遍QAQ,我$WA$的一声就哭了出来啊QAQ B  好像很水的乱扫就好了,m ...

  7. 《高性能MySQL》笔记-BLOB与TEXT

    BLOB和TEXT都是为存储很大的数据而设计的字符串数据类型,分别采用二进制和字符方式存储. 实际上,它们分别属于两组不同的数据类型家族: 字符类型是TINYTEXT,SMALLTEXT,TEXT,M ...

  8. cogs 167. [USACO Mar07] 月度花费

    167. [USACO Mar07] 月度花费 ★★   输入文件:expense.in   输出文件:expense.out   简单对比时间限制:1 s   内存限制:128 MB Farmer ...

  9. ZooKeeper的原理(转)

    一.ZooKeeper的角色 领导者(Leader),负责进行投票的发起和决议,更新系统状态. 学习者(Learner),包括跟随者(Follower)和观察者(Observer),Follower用 ...

  10. Oracle推断值为非数字

    select * from product_info t where t.contract_detailid is not null and length(translate(t.contract_d ...