主要通过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贝塞尔曲线应用-跳动的水滴的更多相关文章
-
Android 贝塞尔曲线 折线图
1.贝塞尔曲线:http://baike.baidu.com/view/60154.htm,在这里理解什么是贝塞尔曲线 2.直接上图: 3.100多行代码就可以画出贝塞尔曲线,直接上代码 packag ...
-
Android -- 贝塞尔曲线公式的推导
1,最近看了几个不错的自定义view,发现里面都会涉及到贝塞尔曲线知识,深刻的了解到贝塞尔曲线是进阶自定义view的一座大山,so,今天先和大家来了解了解. 2,贝塞尔曲线作用十分广泛,简单举几个的栗 ...
-
Android -- 贝塞尔曲线公式的推导和简单使用
1,最近看了几个不错的自定义view,发现里面都会涉及到贝塞尔曲线知识,深刻的了解到贝塞尔曲线是进阶自定义view的一座大山,so,今天先和大家来了解了解. 2,贝塞尔曲线作用十分广泛,简单举几个的栗 ...
-
Android 贝塞尔曲线解析
相信很多同学都知道"贝塞尔曲线"这个词,我们在很多地方都能经常看到.利用"贝塞尔曲线"可以做出很多好看的UI效果,本篇博客就让我们一起学习"贝塞尔曲线 ...
-
Android 贝塞尔曲线的浅析
博客也开了挺长时间了,一直都没有来写博客,主要原因是自己懒---此篇博客算是给2017年一个好的开始,同时也给2016年画上一个句点,不留遗憾. 那就让我们正式进入今天的主题:贝塞尔曲线. 首先,让我 ...
-
Android 贝塞尔曲线库
最近做的一个小项目需要绘制一些折线图,AChartEngine其实里面包含很多图,虽然是开源的,但毕竟不是自己写的,而且项目稍有点庞大,有些东西修改起来还是得花点时间的,所以最后打算自己写一个,参考了 ...
-
Android 贝塞尔曲线
博客图片备份位置:
-
Android中贝塞尔曲线的绘制方法
贝塞尔曲线,很多人可能不太了解,什么叫做贝塞尔曲线呢?这里先做一下简单介绍:贝塞尔曲线也可以叫做贝济埃曲线或者贝兹曲线,它由线段与节点组成,节点是可拖动的支点,线段像可伸缩的皮筋.一般的矢量图形软件常 ...
-
android 利用Path.cubicTo 画 贝塞尔曲线
Path.cubicTo void android.graphics.Path.cubicTo(float x1, float y1, float x2, float y2, float x3, fl ...
随机推荐
-
position之absolute与relative 详解
absolute:绝对定位: relative:相对定位: 唉,以前只是知是知道这两个单词的汉语意思,然后呢,,,怎么用...也是摸凌两可的用.终于抽出时间来看看了: 1.绝对定位:absulute ...
-
Yii常用路径说明
原作者地址:http://www.kuitao8.com/20140520/2483.shtml //framework路径 Yii::getFrameworkPath(); //protected/ ...
-
jquery实现表格内容筛选
对于表格来说,当数据比较多的时候,我们无法一页一页的查找,这时可以通过一个搜索框来实现搜索. 对于这个搜素框,我们为了更好的体验可以利用keyup事件实现在用户输入的时候就开始筛选,而不是填完以后点击 ...
-
新Android工程src和layout文件夹为空
问题:SDK和ADT版本冲突 解决方案: 1.菜单->Help->Install New Software.. 2.在work with放入地址:http://dl-ssl.google ...
-
第3组UI组件:AdapterView及其子类
1 AdapterView类简介 1.1 AdapterView组件是一组重要的组件,AdapterView本身是一个抽线类,实际使用更多的都是Adapter相关子类,AdapterView具有如下特 ...
-
WP8.1 页面导航 缓存问题
最近开始学习wp8.1开发,在页面的导航学习时发现了一点问题,即当使用Frame.Navigate()方法进行页面的跳转时,每次都会重新实例化一个页面.而在新的页面采用Frame.GoBack()或者 ...
-
selenium的Python使用(一)浏览器驱动的安装及使用
一.selenium的安装 直接使用pip进行安装 pip install selenium #(安装最新版本) pip install selenium==3.6.0 #(安装指定版本) ...
-
tensorflow保存读取-【老鱼学tensorflow】
当我们对模型进行了训练后,就需要把模型保存起来,便于在预测时直接用已经训练好的模型进行预测. 保存模型的权重和偏置值 假设我们已经训练好了模型,其中有关于weights和biases的值,例如: im ...
-
python elasticsearch 批量写入数据
from elasticsearch import Elasticsearch from elasticsearch import helpers import pymysql import time ...
-
微信跳转外部浏览器下载app
很多朋友问我怎么解决微信内点击链接或扫描二维码可以直接跳出微信在外部浏览器打开网页链接和下载APP,其实这并不难,只要我们实现微信跳转功能即可.下面给大家介绍这个功能 方案实现教程:http://sk ...