从 0 到 1Android 自定义 View(四)贝塞尔曲线

1,022 阅读5分钟

Android.jpg

前言

扯来扯去,前面三篇自定义 View 文章,终于扯完了一些知识点,有些枯燥,所以我也是讲下核心点,没有细分析,主要是让各位有点印象和了解。这篇终于是实践,敲代码的了,因为工作原因,这篇拖的比较久,不过这系列会一直更新下去的,会把我工作中用到的自定义 View 也会加上去。好了,回归正原题,说到自定义 View ,似乎都离不开贝塞尔曲线,因此,第一篇实践就是与贝塞尔曲线有关的。

目录

从0到1Android自定义View(四) 贝塞尔曲线.png

一、贝塞尔曲线

1、贝塞尔曲线简介

来看看官方对神奇的赛贝尔曲线的介绍:贝塞尔曲线于 1962,由法国工程师皮埃尔·贝塞尔所广泛发表,他运用贝塞尔曲线来为汽车的主体进行设计。贝塞尔曲线最初由 Paul de Casteljau 于 1959 年运用 de Casteljau 演算法开发,以稳定数值的方法求出贝兹曲线。贝塞尔曲线主要用于二维图形应用程序中的数学曲线,曲线由起始点,终止点(也称锚点)和控制点组成,通过调整控制点,贝塞尔曲线的形状会发生变化。

看完后是不是一脸蒙蔽,一句话理解贝塞尔曲线就是:将任意一条曲线转化为精确的数学公式。

2、赛贝尔曲线公式

竟然说了是将曲线转化为精确的数学公式,那么我们来看下具体的数学公式( 注:以下公式中,B(t) 为 t 时间下点的坐标; P0 为起点,Pn 为终点,Pi 为控制点 ):

(1) 一阶贝塞尔曲线(线段)

由 P0 至 P1 的连续点, 描述的一条线段

一阶贝塞尔曲线公式.jpg

一阶贝塞尔曲线公式图.jpg

(2) 二阶贝塞尔曲线(抛物线):

由 P0 至 P1 的连续点 Q0,描述一条线段。

由 P1 至 P2 的连续点 Q1,描述一条线段。

由 Q0 至 Q1 的连续点 B(t),描述一条二次贝塞尔曲线。

二阶贝塞尔曲线(抛物线)公式.jpg

二阶贝塞尔曲线(抛物线)公式图.jpg

(3) 三阶贝塞尔曲线:

三阶贝塞尔曲线公式.jpg

三阶贝塞尔曲线公式图.jpg

3、贝塞尔曲线在 Android 中的应用

其实贝塞尔曲线在 Android 自定义 View 中运用还是挺多的,比如

  • Android 5.0 后下拉刷新的阴影曲线
  • QQ 消息提醒的小红点
  • 用于左右滑动时显示个数的点的移动动画
  • 水流波动效果
  • 一个弹性效果的抽屉菜单

4、Android Path 类中提供贝塞尔曲线的操作方法

在 Android 开发中,要实现贝塞尔曲线其实还是很简单的,因为 Android 已经给我们提供了相关接口,此接口方法在 Path 类中,而关于 Path 类的讲解,前面一篇博客就介绍过了。而且通过 Android 的 API 可以知道,贝塞尔曲线从 API1 就开始支持了。下面就是赛贝尔曲线对应的 API 方法了。

贝塞尔曲线 对应的方法 演示动画
一阶曲线
(线性曲线)
lineTo
一阶贝塞尔曲线动图.gif
二阶曲线 quadTo
二阶贝塞尔曲线(抛物线)动图.gif
三阶曲线 cubicTo
三阶贝塞尔曲线动图.gif
四阶曲线
四阶贝塞尔曲线动图.gif

5、通过 de Casteljau 算法绘制贝塞尔曲线

上面提过,Path 类中提供了画一到三阶的贝塞尔曲线的方法,如果我们需要绘制更高阶的贝塞尔曲线呢?我们可以采用德卡斯特里奥算法(De Casteljau’s Algorithm)来实现贝塞尔曲线。

效果图:

贝塞尔曲线截屏1.gif

贝塞尔曲线截屏2.gif

贝塞尔曲线截屏3.gif

贝塞尔曲线截屏4.gif

Github 上的代码:beziercurve

里面主要就一个类,beziercurve ,这是个自定义 View ,BezierCurve 里面主要提供了以下的方法:

Methods:
method 方法 description 描述
void start() 开始贝塞尔曲线(required)
void stop() 停止贝塞尔曲线(optional)
boolean addPoint() 增加控制点(optional)
boolean delPoint() 删除控制点(optional)
int getOrder() 获取贝塞尔曲线阶数(optional)
void setRate(int rate) 设置移动速率(optional)
void setTangent(boolean tangent) 设置是否显示切线(optional)
void setLoop(boolean loop) 设置是否循环(optional)
void setOrder(int order) 设置贝塞尔曲线阶数(optional)

最后通过 BezierCurveActivity 来展示。

二、贝塞尔曲线的应用

1.QQ 消息提醒可拖拽红点

Github 上的项目地址:qqmsgnotify

效果图:

QQ消息提醒红点.gif

主要是在绘制红点的时候运用了贝塞尔曲线,在固定的位置中,拖拽的时候,有一种粘性的效果,就是这里运用了贝塞尔曲线。

QQ消息提醒红点.png

运用:

(1) 在对应的位置创建一个 TextView
(2) 设置 GooViewListener 监听事件就可以了


 mTvPoint = (TextView) findViewById(R.id.point_conversation);
        mTvPoint.setText("10");
        mTvPoint.setTag(10);
        GooViewListener listener = new GooViewListener(this, mTvPoint) {
            @Override
            public void onDisappear(PointF mDragCenter) {
                super.onDisappear(mDragCenter);
                Toast.makeText(QQMsgNotifyActivity.this, "消失了", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onReset(boolean isOutOfRange) {
                super.onReset(isOutOfRange);
                Toast.makeText(QQMsgNotifyActivity.this, "重置了", Toast.LENGTH_SHORT).show();
            }
        };
        mTvPoint.setOnTouchListener(listener);

2.Viewpage页面引导切换动画

Github 上的项目地址:guideview

效果图:

ViewPage引导动画.gif
)

其实这个例子也是,运用贝塞尔曲线也就是在绘制那个圆形的地方而已,其他地方基本不怎么使用贝塞尔曲线。