安卓开发之使用PathMeasure自定义加载动画控件
来源:互联网 发布:人工智能用go语言开发 编辑:程序博客网 时间:2024/05/21 18:46
先上效果图:
一、PathMeasure
在绘制画布时,我们通常会使用Path对象来勾勒出绘制的路径,而PathMeasure可以让我们得到路径上的一些信息,比如获取路径上点的坐标,截取路径上的某一段小路径等。。
它主要有既个方法:
setPath(Path path, boolean forceClosed);
与一个Path对象绑定,forceClose为true时,不管关联的Path是否是闭合的,都会被闭合。
getLength()
获取路径的长度
getPosTan(float distance, float pos[],float tan[])
distance 为一个 0 - getLength() 之间的值,根据这个距离值计算出当前点的xy坐标和正切值封装到 pos和tan当中;
boolean getSegment (float startD, float stopD, Path dst, boolean startWithMoveTo)
判断截取路径成功时返回true;
startD为开始截取位置距离 Path 起点的长度
stopD 结束截取位置距离 Path 起点的长度
取值范围: 0 <= startD < stopD <= Path总长度getLength(),超过范围截取不成功截取的 Path 将会添加到 dst 中
startWithMoveTo 起始点是否使用 moveTo,用于保证截取的 Path 第一个点位置不变(一般为true)
在默认开启硬件加速的情况下,更改 dst 的内容后可能绘制会出现问题,可以给 dst 添加一个操作:dst.lineTo(0, 0)
二、自定义动画控件
大概思路就是:
创建一个勾勒空心圆的Path对象
再根据上面的Path对象创建PathMeasure对象
最后再通过属性动画不断动态获取startD和stopD的值,并更新View
public class LoadingCircleView extends View { private Path path; private PathMeasure pathMeasure; private Path dst; // 被截取的路径 private Paint paint; // 画笔 // View的宽高 private int height; private int width; private float radius; // 空心圆的半径 private float mLength; // path路径的长度 ValueAnimator valueAnimator; // 属性动画 private float mAnimatorValue; // 属性动画返回的百分比 private float stop; // 截取路径时的stopD值 private float start; // 截取路径时的startD值 public LoadingCircleView(Context context) { super(context); init(); // 初始化 } public LoadingCircleView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public LoadingCircleView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } @TargetApi(Build.VERSION_CODES.LOLLIPOP) public LoadingCircleView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); init(); } private void init() { radius = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,21,getContext().getResources().getDisplayMetrics()); // 初始化半径 path = new Path(); dst = new Path(); paint = new Paint(); pathMeasure = new PathMeasure(); // 设置画笔属性 paint.setAntiAlias(true); paint.setColor(0xbfe46d32); paint.setStyle(Paint.Style.STROKE); paint.setStrokeCap(Paint.Cap.ROUND); paint.setStrokeWidth(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,3.5f,getContext().getResources().getDisplayMetrics())); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); width = w; height = h; // 勾勒空心圆 path.reset(); path.addCircle(width/2,height/2,radius, Path.Direction.CW); // 生成pathMeasure对象 pathMeasure.setPath(path,true); // 获取path的长度 mLength = pathMeasure.getLength(); // 通过属性动画取得百分比值,并更新View valueAnimator = ValueAnimator.ofFloat(0,1); valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { // 获取动画进行的百分比 mAnimatorValue = (float) animation.getAnimatedValue(); postInvalidate(); // 更新界面 } }); // 设置动画的属性 valueAnimator.setDuration(2100); valueAnimator.setRepeatCount(1000); valueAnimator.setRepeatMode(ValueAnimator.RESTART); valueAnimator.start(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); // 只对EXACTLY的条件的宽高处理 setMeasuredDimension(Math.min(widthSize,heightSize),Math.min(widthSize,heightSize)); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // 为加强动画效果,每次对画布旋转不同角度 canvas.rotate(360.0f*mAnimatorValue-45.0f,width/2,height/2); // 初始化截取的路径 dst.reset(); dst.lineTo(0,0); // 消除硬件加速的影响 // 更新截取的开始值和结束值:当mAnimatorValue为0或1时,两个值相等 stop = mAnimatorValue*mLength; start = (float) (stop - ((0.5 - Math.abs(mAnimatorValue - 0.5)) * mLength)); // 截取路径后,并绘制路径 pathMeasure.getSegment(start, stop, dst, true); canvas.drawPath(dst,paint); }}
参考:
PathMeasure之迷径追踪
- 安卓开发之使用PathMeasure自定义加载动画控件
- 安卓开发之自定义粒子旋转动画加载控件
- 安卓开发之自定义动画控件BatteryView(电池加载动画)
- Android使用PathMeasure实现加载动画
- 安卓自定义View进阶-PathMeasure
- 安卓自定义控件之带有折叠动画的ExpandableListView
- 安卓自定义View进阶-Path之玩出花样(PathMeasure)
- 安卓自定义View进阶:Path之玩出花样(PathMeasure)
- 安卓动画搜索框自定义控件
- 安卓自定义控件-实现IOS版UC浏览器三点加载动画效果
- 使用PathMeasure实现 动画CheckBox
- 使用PathMeasure制作Loading动画
- 安卓开发之自定义控件实现画板
- 安卓开发之自定义控件实现MaterialEditText
- 安卓开发之自定义控件实现MaterialEditText
- 安卓控件属性动画使用大全
- 安卓ProgressDialog实现自定义Diallog加载动画
- 安卓自定义控件之饼图
- React实战-如何在ReactJs中调用Google、Baidu地图
- appium2 虚拟机调试
- 插入排序
- comparator接口与Comparable接口
- 有关jsp和servlet
- 安卓开发之使用PathMeasure自定义加载动画控件
- 计算机网络学习小结
- 设计模式——责任链模式
- 漫谈QWidget及其派生类(菜单、菜单栏)
- 【bestcoder】Find Q(简单思维)
- String.valueOf() 方法的使用
- 深入体验C语言项目开发
- WebSocket入门
- 流程控制语句