1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > Android自定义控件开发入门与实战(6)路径动画 android脚本开发工具

Android自定义控件开发入门与实战(6)路径动画 android脚本开发工具

时间:2019-08-17 00:26:33

相关推荐

Android自定义控件开发入门与实战(6)路径动画 android脚本开发工具

前面几章所讲的内容其实都只是比较普通、简单的动画,这章开始学习较难、较为有深度、也比较可以实现更加炫酷效果的动画,通过PathMeasure和SVG动画来实现。

PathMeasure实现路径动画

PathMeasure是Android官方API,是之前第一张关于路径只是的一个扩展,十分的有用。

PathMeasure可以计算出路径的总长、指定长度所对应的坐标等等路径信息。

有两种初始化方式:

第一种:

PathMeasure pathMeasure = new PathMeasure();

直接new一个,然后接下来通过PathMeasre的setPath()绑定PathMeasure和Path

setPath(Path path,boolean forceClosed)

这样就完成初始化,接着就可以用pathMeasure来调用关于路径的信息辽。

第二种方法:

直接通过PathMeasure构造方法初始化。

PathMeasure(Path path,boolean forceClosed);

这两种方法都会涉及到的forceClosed是计算path是否闭合,但是path的闭合并不是由forceClosed控制,绘制出来时,path该闭合还是闭合,不闭合就是不闭合,但是如果forceClosed设置为true时,会当做path闭合,把闭合的路径算进去。

一些简单的函数使用

1、getLength()

public float getLength()

该函数的作用为计算路径长度,使用非常广泛。

我们用路径来画一个没有闭合的正方形:

canvas.translate(50, 50);

Path path = new Path();

path.moveTo(0, 0);

path.lineTo(0, 100);

path.lineTo(100, 100);

path.lineTo(100, 0);

PathMeasure pathMeasure1 = new PathMeasure(path, false);

PathMeasure pathMeasure2 = new PathMeasure(path, true);

Log.e(TAG, "forceClose = false : " + pathMeasure1.getLength());

Log.e(TAG, "forceClose = true : " + pathMeasure2.getLength());

canvas.drawPath(path,paint);

打出的第一个Log长度为300,而第二个则为400.因为第二个已经考虑到闭合了。

2、isClose()

判断测量的path是否闭合。

如果PathMeasurei的forceClosed设置为true时,则isClosed()一定为true

3、nextContour()

Path可以有很多曲线、线段构成,但是getLength()只会取第一条线进行计算。

而nextContour()是跳转到下一条曲线的函数。如果跳转成功则返回true,否则返回false。

注:pathMeasure.getLength()只针对第一条曲线

getSegment

用法

boolean getSegment(float startD,float stopD,Path dst,boolean startWithMoveTo);

顾名思义,这个函数用截取一个Path中的某一个片段。

通过参数startD和stopD来控制截取的长度。并将截取后的Path保存到参数dst中。

最后一个参数startWithMoveTo表示起始点是否使用moveTo将路径的新起始点移到结果Path的起始点,通常设置为true。用来保证每次截取segment都是连续的、完整的。

其中startD为开始截取位置距离Path起点的长度,stopD为结束时截取位置距离Path起点的长度。如果startD和stopD的范围不再Path的长度范围内或者 startD==stopD该函数返回false

如果在开启硬件加速并使用该方法,绘图会出现问题,所以在使用getSegment时要禁用硬件加速。

这里来截取一个path,代码如下:

canvas.translate(100, 100);

Path path = new Path();

path.addRect(-50,-50,50,50, Path.Direction.CW);

Path dst = new Path();

PathMeasure pathMeasure = new PathMeasure(path, false);

pathMeasure.getSegment(0,150,dst,true);

canvas.drawPath(dst, paint);

截取的path如下

这说明截取是左上角开始截取,并且方向是根据Path的绘制方向截取,上面path绘制是CW(顺时针),所以截取了上半部分。

如果dst本来就已经是一个路径,这个时候再去取别的path的路径,会怎么样呢?

答案是 原来的路径不会被覆盖,反而和新的截取到的路径一起绘制出来。

如下图所示:

如果这个时候我们把 PathMeasure的startWithMoveTo改为false会怎么样呢?下过如下所示:

这里咋一看不是很好理解,其实画个图就ok,因为startWithMoveTo设置为false就是将新的Path的起始点拉到自己原本dst的结束点(因为dst自己画的是不能变的) ,然后目标path其他位置的点不变

就像是使用processon、viso软件画图的时候,用一条线的起点去连另一条线的终点这样。

示例

路径绘制是PathMeasure最常用的功能,下面实现一个转圈圈的加载效果图。

思路是通过ValueAnimator动画算出当前的动画的进度,通过进度获取转圈圆的周长,拿到周长后通过PathMeasure的getLength和getSegment去画圆。

我们再构造函数中做new的操作:

public PathMeasureView1(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

paint = new Paint(Paint.ANTI_ALIAS_FLAG);

setLayerType(LAYER_TYPE_SOFTWARE, null);

paint.setStrokeWidth(4);

paint.setStyle(Paint.Style.STROKE);

paint.setColor(Color.RED);

dst = new Path();

circlePath = new Path();

circlePath.addCircle(100, 100, 50, Path.Direction.CW);

pathMeasure = new PathMeasure(circlePath, true);

ValueAnimator animator = ValueAnimator.ofFloat(0, 1);

animator.setRepeatCount(ValueAnimator.INFINITE);

animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

@Override

public void onAnimationUpdate(ValueAnimator animation) {

drawProgress = (float) animation.getAnimatedValue();

invalidate();

}

});

animator.setInterpolator(new AccelerateInterpolator());

animator.setDuration(2000);

animator.start();

}

之后再draw函数中做下面的操作:

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

canvas.drawColor(Color.WHITE);

float stop = pathMeasure.getLength() * drawProgress;

dst.reset();

pathMeasure.getSegment(0, stop, dst, true);

canvas.drawPath(dst, paint);

}

最后效果如下所示:

但是这个加载圈的起点一直在画圆的起点,和我们平时看到的加载圆有点不一样,所以我们可以去改变它的起始点,来让圆更加生动:

当动画开始到一半的时候,起点都是最开始的画圆的起点,到后半段,dst圆的起始点开始逐渐向结束点靠拢,最后到达开始位置的时候,两个端点重合

可以得出当

进度drawProgress< 0.5时 startD=0

进度drawProgress>0.5时 startD=(2*drawProgress-1)*length

通过合并公式可以得出 startD = stopD - (0.5 - |drawProgress - 0.5| )*length

float start = (float) (stop - (0.5 - Math.abs(drawProgress - 0.5)) * pathMeasure.getLength());

pathMeasure.getSegment(start, stop, dst, true);

canvas.drawPath(dst, paint);

这就很顶啦。

getPosTan()

getPosTan()函数用于得到路径上某一长度的位置以及该位置的正切值。

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

float distance: 距离Path起始点的长度,取值范围为0≤distance≤getLength

float[]pos:该点的坐标值 pos[0]表示x坐标 pos[1]表示y坐标

最后

简历首选内推方式,速度快,效率高啊!然后可以在拉钩,boss,脉脉,大街上看看。简历上写道熟悉什么技术就一定要去熟悉它,不然被问到不会很尴尬!做过什么项目,即使项目体量不大,但也一定要熟悉实现原理!不是你负责的部分,也可以看看同事是怎么实现的,换你来做你会怎么做?做过什么,会什么是广度问题,取决于项目内容。但做过什么,达到怎样一个境界,这是深度问题,和个人学习能力和解决问题的态度有关了。大公司看深度,小公司看广度。大公司面试你会的,小公司面试他们用到的你会不会,也就是岗位匹配度。

选定你想去的几家公司后,先去一些小的公司练练,学习下面试技巧,总结下,也算是熟悉下面试氛围,平时和同事或者产品PK时可以讲得头头是道,思路清晰至极,到了现场真的不一样,怎么描述你所做的一切,这绝对是个学术性问题!

面试过程一定要有礼貌!即使你觉得面试官不尊重你,经常打断你的讲解,或者你觉得他不如你,问的问题缺乏专业水平,你也一定要尊重他,谁叫现在是他选择你,等你拿到offer后就是你选择他了。

金九银十面试季,跳槽季,整理面试题已经成了我多年的习惯!在这里我和身边一些朋友特意整理了一份快速进阶为Android高级工程师的系统且全面的学习资料。涵盖了Android初级——Android高级架构师进阶必备的一些学习技能。

附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题(含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)

本文在开源项目:【GitHub 】中已收录,里面包含不同方向的自学编程路线、面试题集合/面经、及系列技术文章等,资源持续更新中…

真题(含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)

[外链图片转存中…(img-AypROxVr-1644997512950)]

本文在开源项目:【GitHub 】中已收录,里面包含不同方向的自学编程路线、面试题集合/面经、及系列技术文章等,资源持续更新中…

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。