Android自定义view Path 的高级用法之搜索按钮动画
作者:WangRain1 发布时间:2023-12-23 06:53:28
关于Path之前写的也很多了,例如path绘制线,path绘制一阶,二阶和三阶贝塞尔路径,这些都是path的基本用法。今天我要带大家看的是Path 的高级用法,先上图,再吹。
效果大致是这样的。看着是不是挺好。话不多说,切入正题:
既然今天要谈Path的高级用法,那就先来讲一讲(Path -- 中文 )就是“路径”既然是路径,从我们面向对象的想法的话,我们就容易想到 路径 的长度,路径的某一点等。想到这里我们就引出今天 的主要 类--------PathMeasure,字面意思很容易理解--翻译成 路径测量。对这就是我们用来测量路径的类。既然是一个类,我们就要看他集体有哪些方法和属性。
1.构造方法:
一个是有参数,一个无参数。
无参数就很容易理解就是直接创建对象,那有参数呢?
PathMeasure(Path path, boolean forceClosed) ;
第一个参数 Path 咿 !这不就是我们的Path 了吗。对既然是测量类,那就是要确定需要测量的那个路径,那第二个参数呢?
第二个参数是用来确保 Path 闭合,如果设置为 true, 则不论之前Path是否闭合,都会自动闭合该 Path(如果Path可以闭合的话)。
2.方法:
这方法还挺多,都是干啥的呢?就找几个重要的,常用的讲讲:
第一个那就是 setPath(Path path, boolean forceClosed)
这方法一看就知道设置path 路径的,就是如果我们创建 PathMeasure,时用的是无参的构造方法时 ,这时候就要用此方法,告诉PathMeasure 当前需要测量的是哪一个path路径。(个人喜欢用无参,比较灵活)。
第二个那就是getLength(),很容易理解就是 获得 path 的总长度。
第三个:getSegment(float startD, float stopD, Path dst, boolean startWithMoveTo),这个方法非常重要,截取片段,截取的结果就是,我们的path路径。参数也很好理解。第一个是开始的距离,第二个是结束的距离(相对于起点==既然是起点,我们怎么找他们的起点呢,其实就是我们绘制图画笔开始的哪一点)。第三个参数就是返回的路径。第四个参数起始点是否使用 moveTo 用于保证截取的 Path 第一个点位置不变。
第四个:getPosTan(float distance, float[] pos, float[] tan),这个也是非常重要的,为什么呢?听我解释一下他的参数就知道了。第一个参数是距离(相对于绘制起点的路径距离),第二个参数是距离起点的坐标点,第三个参数返回的是正玄函数tan@角度。
对这些参数了解之后下面就来讲解我们今天的例子:
首先我们先来个简单的:例如
如图这样的分析过程:
1.首先绘制一个圆(蓝色的),从45度开始绘制,注意圆的起点。
2.同圆心绘制大圆(辅助圆)用来辅助绘制蓝色的线。
3.通过getPosTan(float distance, float[] pos, float[] tan)方法得到两个圆的终点的坐标。
4.利用lineTo(x,y)绘制线。就得到我们的搜索图形了。
5.接下来就是实时 截取片段。getSegment(float startD, float stopD, Path dst, boolean startWithMoveTo),截取从距离0到getlength();这样就产生了一个动态的效果了。
看代码:
关于画笔,canvas画布,valueanimator动画,这些请看之前的博客,都有详细讲解。
public class MySearch extends View {
Paint paint;
Path searchPath; //搜索的圆
Path ciclePath; //外圆
//获得宽高
int w;
int h;
//这是保存截取时,返回的坐标点
float serpos[];
float cicpos[];
//测量 path 的类
PathMeasure measure;
//动画产生的实时数据
float value;
public MySearch(Context context) {
this(context,null);
}
public MySearch(Context context, @Nullable AttributeSet attrs) {
this(context,attrs,0);
}
public MySearch(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
//获得屏幕的宽高
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
w = wm.getDefaultDisplay().getWidth();
h = wm.getDefaultDisplay().getHeight();
//初始化数据
serpos = new float[2];
cicpos = new float[2];
//画笔
paint = new Paint();
paint.setStyle(Paint.Style.STROKE);
paint.setDither(true);
paint.setStrokeWidth(6);
paint.setAntiAlias(true);
//初始化路径
initPath();
//初始化动画
initAnimator();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//移动画布的远点到屏幕中心
canvas.translate(w/2,h/5);
paint.setColor(Color.BLUE);
//这是截取方法返回的路径
Path dra = new Path();
//解除硬件加速,不然没效果
dra.reset();
dra.lineTo(0,0);
//设置当前需要测量的path
measure.setPath(searchPath,false);
//开始截取
boolean s = measure.getSegment(measure.getLength()*value,measure.getLength(),dra,true);
//绘制路径
canvas.drawPath(dra,paint);
}
/**
* 初始化路径
*/
public void initPath(){
paint.setColor(Color.BLUE);
//搜索的圆
searchPath = new Path();
RectF rectF = new RectF(-50,-50,50,50);
searchPath.addArc(rectF,45,359.9f);
//辅助圆
ciclePath = new Path();
RectF rectF1 = new RectF(-100,-100,100,100);
ciclePath.addArc(rectF1,45,359.9f);
//测量类
measure = new PathMeasure();
measure.setPath(searchPath,false);
//获取坐标
measure.getPosTan(0,serpos,null);
measure.setPath(ciclePath,false);
//获取坐标
measure.getPosTan(0,cicpos,null);
//根据两点坐标绘制线
searchPath.lineTo(cicpos[0],cicpos[1]);
}
/**
* 初始化动画
*/
public void initAnimator(){
ValueAnimator animator = ValueAnimator.ofFloat(0,1);
animator.setDuration(2600);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
value = (float) animation.getAnimatedValue();
postInvalidate();
}
});
animator.start();
}
}
第一个图大家学会了,去练习一下吧!
来源:http://blog.csdn.net/wangrain1/article/details/72898014
猜你喜欢
- 面试题1:说一下你对ReentrantLock的理解?ReentrantLock是JDK1.5引入的,它拥有与synchronized相同的
- 总结并复现了一下Unsafe在安全领域的一些应用0 前言unsafe里面有很多好用的方法,比如allocateInstance可以直接创建实
- 前言本篇文章主要介绍关于我在SpringBoot中使用MyBatis-Plus是如何解决Invalid bound statement (n
- 1.浅复制与深复制概念 ⑴浅复制(浅克隆) 被复制对象的所有变量都含有与原来的对象相同的值,
- 前言今天重新装了IDEA2020,顺带重装了一些插件,毕竟这些插件都是习惯一直在用,其中一款就是Mybatis Log plugin,按照往
- 子类重新实现父类的方法称重写;重写时可以修改访问权限修饰符和返回值,方法名和参数类型及个数都不可以修改;仅当返回值为类类型时,重写的方法才可
- 这篇文章主要介绍了Mybatis模糊查询及自动映射实现详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要
- 我们第三章分析过客户端接入的流程, 这一小节带大家剖析客户端发送数据, Server读取数据的流程:首先温馨提示, 这一小节高度耦合第三章的
- lambda表达式以及并行流。官方承诺你写出来的代码更运行得更快。流会自动通过Fork/Join池并行地执行。我听过一些关于Java 8的主
- JNDI的理解JNDI是 Java 命名与文件夹接口(Java Naming and Directory Interface),在J2EE规
- 本文实例讲述了C#判断一天、一年已经过了百分之多少的方法。分享给大家供大家参考。具体如下:这里写了四个函数,分别是1.判断当前时间过了今天的
- 堆排序介绍:堆排序可以分为两个阶段。在堆的构造阶段,我们将原始数组重新组织安排进一个堆中;然后在下沉排序阶段,我们从堆中按顺序取出所有元素并
- 背景:用习惯了idea再去用eclipse实在用的不习惯,于是将老的eclipse项目导入到eclipse,网上有很多教程,看了很多博客都不
- 前言Kotlin并没有想象中的那么牛逼哄哄,也并不难,我更喜欢把他看做一枚语法糖,所谓的语法糖就是:能够让代码变得更加简单易读的辅助工具。而
- 一、前言随着微服务治理手段越来越多,对开发者来说,不同微服务之间的接口调用是日常开发中非常普遍的事情,以springcloud生态体系的微服
- 1、线性表定义线性表是最基本、最简单、也是最常用的一种数据结构。线性表(linear list)是数据结构的一种,一个线性表是n个具有相同特
- 今天遇到pom中添加dependency时相关的jar会自动下载,但是左边的External Libraries中一直获取不到添加的jar问
- 前言使用递归循环开发评论回复功能,适用于大部分的简单单体应用评论功能或许是大多数的单体应用之中会用到的功能,我们会在自己所开发的项目之中进行
- 使用System.Threading.Thread类可以创建和控制线程。常用的构造函数有: // 摘要: // 初
- Android安装apk文件并适配Android 7.0详解首先在AndroidManifest.xml文件,activity同级节点注册p