自定义控件:菜单按钮关联动画控件(仿toolbar)详解

来源:互联网 发布:小说编辑软件 编辑:程序博客网 时间:2024/06/06 07:29

支持原创哦。yhGO。

 

项目中需要一个这样的控件,本来是从网上下了一个写好的仿ToolBar控件,但是一看惨不忍睹,只实现了开始和结束两个状态。中间过程的线条变换杂乱无章。又正好学习完Path之后技痒难耐。嘿嘿。。。就自己试着写了一个。

 

 

效果:

 

 



 

就是这个菜单按钮随着侧滑菜单的打开,从横着的三条杠变为一个向左的箭头。

 

 

优势:

可以与任意侧滑菜单控件等结合使用。比toolbar的该效果使用起来灵活很多。

原理:

让我再看一下分解图片:


相信大家看过效果图之后,都能明白,这个效果说白了就是对那三条线进行位移旋转变换。而难点在于怎么让这三条线在变幻的时候还能是一个整体,而不是各变各的显得杂乱无章。

好了,废话不说,开始分析:

 

首先,我们应该再把这个效果简化一些。我们知道两点确定一条直线,所以,我们可以将上面三条线段的变换转化为6个点的变换。

 

如图所示A,B,C,D,E,F六个点。同时我在图上加了两个辅助圆。点A,B,C,D在圆1上。点E,F在圆2上。圆1,圆2是以点o为圆心的同心圆。半径分别为AOEO。(ps,图是我手绘的,不太标准,大家懂就好~~

 

看到这两个辅助圆,聪明的同学是不是想到什么?教师附身么,啊!!救我!

咳咳,接着我们刚才的思路,将三条线简化为了6个点的变换。那点的变化是什么?点动成线,没错,这两个同心圆就是6个点的变换线路。我们看下一副图:

 

如图所示,灰色的线段bcda,和FE所组成的图形就是我们变换后的箭头。

所以我们可得这6个点的变化

A->a,B->b,E->F,F->E,C->c,D->d

还是那句话,点动成线。既然我们不是只要动画的开始点与结束点。那么便要求出A->a,B->b,E->F,F->E,C->c,D->d这六个变化中的所有点。那就是AaBbEF,FE,Cc,Dd这六条圆弧。

 

我们用Path类中的这个方法来得到一个圆弧:

 public void addArc (RectF oval, float startAngle, float sweepAngle)

 

Oval:用来确定这个圆(椭圆)半径和圆心的矩形。

startAngle:开始的角度。

sweepAngle:这个圆弧划过的角度。

注:Android中的正角度为顺时针方向。

 

 

 

下面我就以点A为例,求得A->a这一段圆弧。

 

首先确定oval。也就是内切圆1的正方形。可知,该正方形的宽高等于圆1的直径。聪明的同学这是在内心估计已经开始吐槽了。。绕了一大圈不就是求AO的长嘛。对的!真聪明,哈。我们设线段AB的长为m,初始时三条线段间的宽相等为h。AO为:

  flaot AO= Math.sqrt(m*m/4+h*h);

 

以点O为画布坐标原点。

 

矩形为:

RectF rect=new RectF(-AO, -AO,AO,AO);

 

矩形搞定,下面我们求startAngle

 

 

 

根据上图,我们可以知道startAngle=270-角1;

所以关键在于求角1。而我们知道AN和ON的长(宽和高的一半),于是角1的度数呼之欲出~~~~(三角函数,对比邻)

 

float angle1=(float)(Math.toDegrees(Math.atan( (AN/2)/(NO/2))));

 

所以

 

startAngle=270-angle1

sweepAngle=180+angle1;(默认aO垂直于EF

 

三个变量凑齐,召唤神龙!!!!,哦不,是弧线。恩....

接下来,我们进行下一步。什么?你说还有五条弧线。。。duangduangduang,完成!

 

 

接下来,就是根据侧滑菜单的打开程度取这五条弧线上响应的点。

PathMeasue类来完成它。

先将我们的弧线初始化给PahtMeasue

 

 setPath(一条弧线, false);

 

 

接下来核心方法隆重登场:

PathMeasure类中的

     boolean getPosTan (float distance, float[] pos, float[] tan)

方法各个参数释义:

参数

作用

备注

返回值(boolean)

判断获取是否成功

true表示成功,数据会存入 pos 和 tan 中,
false 表示失败,pos 和 tan 不会改变

distance

距离 Path 起点的长度

取值范围: 0 <= distance <= getLength

pos

该点的坐标值

坐标值: (x==[0], y==[1])

tan

该点的正切值

正切值: (x==[0], y==[1])

 

 

用法很简单,将distance,还有创建好的postan(注意tan不能为null)这三个参数传进去。即可得到在弧线上距离弧线起点距离为distance的点的坐标(pos中存放)。

 

接下来将求出来的6个点,对应两点一一连线。

完成!!

 

 

 

Demo

 

github上:ToolBarMenuButton

1 0
原创粉丝点击