自定义控件-类似书签的tab按钮

需求分析

需要做成一个如图的类似书签tab栏。

自定义控件-类似书签的tab按钮_第1张图片
实现思路

直接用selector替换背景肯定可以,但是想试试许久没用的自定义控件。

继承view,onMeasure获得宽高,onDraw绘制背景,绘制选中颜色,绘制文字。看起来十分简单。

然而年轻的我还是太连清了。UI在左右两边分别加了一个圆角,这用路径就很难画了。

本来想用arcTo方法绘制


mPath.arcTo(ovalRectF, startAngle, sweepAngle) , ovalRectF为椭圆的矩形,startAngle 为开始角度,sweepAngle 为结束角度。

但通过尝试发现圆弧的曲率很难计算,画出来的圆弧角度很奇怪,打算使用贝塞尔曲线。

贝塞尔曲线扫盲

贝塞尔曲线不仅能画直线,也能画曲线。即便是更复杂的曲线,控制点的增加也只是线性的。这一特点使其不光在工业设计领域大展拳脚,就连数学基础不好的人也可以比较容易地掌握,比如大多数平面美术设计师们。

简单来说,贝塞尔曲线就是将任意一条曲线转化为准确的数学公式。 Bezier 曲线是用一系列点来控制曲线状态的。

贝塞尔曲线中有一些比较关键的名词,解释如下:

  • 数据点:通常是指一条路径的起始点和终止点

  • 控制点:控制点决定了一条路径的弯曲轨迹,根据控制点的个数,贝塞尔曲线被分为一阶贝塞尔曲线(0个控制点)、二阶贝塞尔曲线(1个控制点)、三阶贝塞尔曲线(2个控制点),以此类推。


    自定义控件-类似书签的tab按钮_第2张图片
Android中的贝塞尔曲线模拟

一般的开发者只考虑二阶贝塞尔曲线和三阶贝塞尔曲线,SDK也只提供了二阶和三阶的API调用。对于再高阶的贝塞尔曲线,通常可以将曲线拆分成多个低阶的贝塞尔曲线,也就是所谓的降阶操作。分别是下列方法

二阶 Path.quadTo()和rQuadTo() 前者基于绝对坐标,后者基于相对坐标。

三阶 Path.cubicTo()和rCubicTo() 前者基于绝对坐标,后者基于相对坐标。(参数比二阶多了一个控制点)

我只是想画一个润滑点的圆弧,所以使用Path.quadTo()方法来绘制圆弧


quadTo(float x1, float y1, float x2, float y2) 

Add a quadratic bezier from the last point, approaching control point (x1,y1), and ending at (x2,y2). 

自定义控件-类似书签的tab按钮_第3张图片

把两条线反向延长,交于一点,这个点就是控制点。(别问我为啥,这个曲率就是刚刚好)

x2,y2是终点的坐标,默认是忽略起始坐标的(起始坐标就是你笔在的位置)

算控制点的过程比较难受,就省略啦。

然后在activity里面和fragment扯上关系就好了。

自定义控件-类似书签的tab按钮_第4张图片
碰到的一些注意点

1. Invalidate方法实现界面刷新,但是Invalidate不能直接在子线程中调用

postInvalidate()可以在子线程中被调用

2. 不要在布局和绘图期间创建对象

3. 写自定义view的时候要注意Android的事件分发机制

dispatchTouchEvent(view的方法)---->onTouch(setontouchlistener)---->onTouchEvent(view的方法)----->onClick(setonclicklistener)

如果是通过重写onTouchEvent()来执行逻辑代码,那么给控件设置setonclicklistener就无效了。

具体的代码可以查看github仓库 点我跳转

参考文章

https://www.jianshu.com/p/55c721887568

https://juejin.im/post/57adbd9c79bc440058c9962d#comment

你可能感兴趣的:(自定义控件-类似书签的tab按钮)