前言
之前没有见到有封装好的类似QQ小红点的控件,虽然公司项目中并没有使用到该效果,不过出于练习与回顾的角度决定自己动手写一个。
贝塞尔曲线
在开始动手写之前,我先介绍一下贝塞尔曲线。贝赛尔曲线(Bézier曲线)是电脑图形学中相当重要的参数曲线。更高维度的广泛化贝塞尔曲线就称作贝塞尔曲面,其中贝塞尔三角是一种特殊的实例。贝塞尔曲线于1962年,由法国工程师皮埃尔·贝塞尔(Pierre Bézier)所广泛发表,他运用贝塞尔曲线来为汽车的主体进行设计。贝塞尔曲线最初由Paul de Casteljau于1959年运用de Casteljau算法开发,以稳定数值的方法求出贝塞尔曲线。
线性贝塞尔曲线
给定点P0、P1,线性贝塞尔曲线只是一条两点之间的直线。这条线由下式给出:
二次方贝塞尔曲线
二次方贝塞尔曲线的路径由给定点P0、P1、P2的函数B(t)追踪:
三次方贝塞尔曲线
P0、P1、P2、P3四个点在平面或在三维空间中定义了三次方贝塞尔曲线。曲线起始于P0走向P1,并从P2的方向来到P3。一般不会经过P1或P2;公式如下:
N次方贝塞尔曲线
贝塞尔曲线代码实现
Android在API=1的时候就提供了贝塞尔曲线的画法,只是隐藏在Path#quadTo()和Path#cubicTo()方法中,一个是二阶贝塞尔曲线,一个是三阶贝塞尔曲线。当然,如果你想自己写个方法,依照上面贝塞尔的表达式也是可以的。不过一般没有必要,因为Android已经在native层为我们封装好了二阶和三阶的函数。
效果分析
首先咱们来看看QQ的效果图,如下:
看到这个效果图,结合上述对贝塞尔的简单描述。你是否已经有想法了?如果有那么请跟着我继续验证你的想法,如果没有请容我向你娓娓道来。
1.首先确定有两个点,这两个点是不一样的。下面是原始红点,上面的手势拖拽之后产生的红点。原始点大小会随着拖拽的距离而逐渐变大,并且当达到阀值会消失。而拖拽点大小始终与原始大小一致保持不变。
2.两点之间的曲线效果。如下图,两条线段,其实就是两条二阶贝塞尔曲线。咱们只要分析出其中一条便可,就拿线1来说吧。贝塞尔曲线1的起点是两个小圆与大圆在某一侧的外切点,控制点是两圆点构成的线段的中心点。
3.如何实现动态变化?这个就好说了,手指移动的时候,小圆不断变化,切点自然也在变,并且两个圆的中心距离位置也是随着改变。
代码实现
梳理完毕之后,咱们就开始撸代码吧。再来回顾前面说的核心内容:1.贝塞尔曲线知识;2.两个圆的变化,以及利用贝塞尔曲线绘制两个圆拉动的效果,并且随着距离变化而变化。OK,下面开始看代码
首先创建类DragPointView并且继承View
public class