Android自定义控件:带你掌握一款多特效的智能loadingView

//其中 default_all_distance = (w - h) / 2;除以2是因为2遍都往中间缩短

private void set_rect_to_circle_animation() {

//这是一个属性动画,current_left 会在duration时间内,从0到default_all_distance匀速变化

//想添加多样化的话 还可以加入插值器。

animator_rect_to_square = ValueAnimator.ofInt(0, default_all_distance);

animator_rect_to_square.setDuration(duration);

animator_rect_to_square.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

@Override

public void onAnimationUpdate(ValueAnimator animation) {

//这里的current_left跟onDraw相关,还记得吗

//onDraw里的控件区域

//控件左边区域 rectf.left = current_left;

//控件右边区域 rectf.right = width - current_left;

current_left = (int) animation.getAnimatedValue();

//刷新绘制

invalidate();

}

});

矩形到圆角矩形。就是从一个没有圆角的变成完全圆角的矩形,当然我展示的时候只有第三个图,最后一个按钮才明显了。

其他的我直接设置成了圆角按钮,因为我把圆角做成了一个属性。

还记得onDraw里的canvas.drawRoundRect(rectf, circleAngle, circleAngle, paint);circleAngle就是圆角的半径

可以想象一下如果全是圆角,那么circleAngle会是多少,当然是height/2;没错吧,所以

因为我把圆角做成了属性obtainCircleAngle是从xml文件获取的属性,如果不设置,则为0,就没有任何圆角效果

animator_rect_to_angle = ValueAnimator.ofInt(obtainCircleAngle, height / 2);

animator_rect_to_angle.setDuration(duration);

animator_rect_to_angle.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

@Override

public void onAnimationUpdate(ValueAnimator animation) {

//这里试想下如果是一个正方形,刚好是圆形的圆角,那就是一个圆

circleAngle = (int) animation.getAnimatedValue();

//刷新绘画

invalidate();

}

});

2个属性动画做好后,用 private AnimatorSet animatorSet = new AnimatorSet();把属性动画加进去,可以设置2个动画同时进行,还是先后顺序 这里是同时进行所用用with

animatorSet

.play(animator_rect_to_square).with(animator_rect_to_angle);

6.2、变成圆形后,有一个loading加载动画

这里就是画圆弧,只是不断改变,圆弧的起始点和终点,最终呈现loading状态,也是在onDraw里

//绘制加载进度

if (isLoading) {

//参数1:绘制圆弧区域

//参数2,3:绘制圆弧起始点和终点

canvas.drawArc(new RectF(width / 2 - height / 2 + height / 4, height / 4, width / 2 + height / 2 - height / 4, height / 2 + height / 2 - height / 4), startAngle, progAngle, false, okPaint);

//这里是我通过实践,实现最佳loading动画

//当然这里有很多方式,因为我自定义这个view想把所有东西都放在这个类里面,你也可以有你的方式

//如果有更好的方式,欢迎留言,告知我一下

startAngle += 6;

if (progAngle >= 270) {

progAngle -= 2;

isAdd = false;

} else if (progAngle <= 45) {

progAngle += 6;

isAdd = true;

} else {

if (isAdd) {

progAngle += 6;

} else {

progAngle -= 2;

}

}

//刷新绘制,这里不用担心有那么多刷新绘制,会不会影响性能

//

postInvalidate();

}

6.3、loading状态,到打勾动画

那么这里首先要把loading动画取消,那么直接改变isLoading=false;不会只它同时启动打勾动画;打勾动画的动画,这里比较麻烦,也是我在别人自定义动画里学习的,通过PathMeasure,实现路径动画

/**

  • 路径–用来获取对勾的路径

*/

private Path path = new Path();

/**

  • 取路径的长度

*/

private PathMeasure pathMeasure;

//初始化打勾动画路径;

private void initOk() {

//对勾的路径

path.moveTo(default_all_distance + height / 8 * 3, height / 2);

path.lineTo(default_all_distance + height / 2, height / 5 * 3);

path.lineTo(default_all_distance + height / 3 * 2, height / 5 * 2);

pathMeasure = new PathMeasure(path, true);

}

//初始化打勾动画

private void set_draw_ok_animation() {

animator_draw_ok = ValueAnimator.ofFloat(1, 0);

animator_draw_ok.setDuration(duration);

animator_draw_ok.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

@Override

public void onAnimationUpdate(ValueAnimator animation) {

startDrawOk = true;

isLoading = false;

float value = (Float) animation.getAnimatedValue();

effect = new DashPathEffect(new float[]{pathMeasure.getLength(), pathMeasure.getLength()}, value * pathMeasure.getLength());

okPaint.setPathEffect(effect);

invalidate();

}

});

}

//启动打勾动画只需要调用

animator_draw_ok.start();

onDraw里绘制打勾动画

//绘制打勾,这是onDraw的,startDrawOk是判断是否开启打勾动画的标识

if (startDrawOk) {

canvas.drawPath(path, okPaint);

}

6.4、loading状态下回到失败样子(有点类似联网失败了)

之前6.1提到了矩形到圆角矩形和矩形到正方形的动画,

那么这里只是前面2个动画反过来,再加上联网失败的文案,和联网失败的背景图即刻

6.5、loading状态下启动扩散全屏动画(重点)

这里我通过loginSuccess里参数的类型启动不同效果:

1、启动扩散全屏动画

public void loginSuccess(Animator.AnimatorListener endListener) {}

2、启动打勾动画

public void loginSuccess(AnimationOKListener animationOKListener) {}

启动扩散全屏是本文的重点,里面还涉及到了一个自定义view

CirclBigView,这个控件是全屏的,而且是从一个小圆不断改变半径变成大圆的动画,那么有人会问,全屏肯定不好啊,会影响布局,

但是这里,我把它放在了activity的视图层:

ViewGroup activityDecorView = (ViewGroup) ((Activity) getContext()).getWindow().getDecorView();

ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);

activityDecorView.addView(circlBigView, layoutParams);

这个灵感也是前不久在学习微信,拖拽退出的思路里发现的。全部代码如下:

public void toBigCircle(Animator.AnimatorListener endListener) {

//把缩小到圆的半径,告诉circlBigView

circlBigView.setRadius(this.getMeasuredHeight() / 2);

//把当前背景颜色告诉circlBigView

circlBigView.setColorBg(normal_color);

int[] location = new int[2];

//测量当前控件所在的屏幕坐标x,y

this.getLocationOnScreen(location);

//把当前坐标告诉circlBigView,同时circlBigView会计算当前点,到屏幕4个点的最大距离,即是当前控件要扩散到的半径

//具体建议读者看完本博客后,去下载玩耍下。

circlBigView.setXY(location[0] + this.getMeasuredWidth() / 2, location[1]);

if (circlBigView.getParent() == null) {

ViewGroup activityDecorView = (ViewGroup) ((Activity) getContext()).getWindow().getDecorView();

ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);

activityDecorView.addView(circlBigView, layoutParams);

}

circlBigView.startShowAni(endListener);

isAnimRuning = false;

}

结束语


因为项目是把之前的功能写成了控件,所以有很多地方不完善。希望有建议的大牛和小伙伴,提示提示我,让我完善的更好。谢谢

希望读到这的您能转发分享和关注一下我,以后还会分享Android知识点及解析,您的支持就是我最大的动力!!

学习分享,共勉


题外话,我从事Android开发已经五年了,此前我指导过不少同行。但很少跟大家一起探讨,正好最近我花了一个多月的时间整理出来一份包括不限于高级UI、性能优化、移动架构师、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter等全方面的Android进阶实践技术,今天暂且开放给有需要的人,若有关于此方面可以关注+点赞后领取,或者评论与我一起交流探讨。

资料免费领取方式:关注+点赞后,加入点击链接加入群聊:Android高级开发交流群(818520403)即可获取免费领取方式!

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级安卓工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Android移动开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
img

尾声

开发是需要一定的基础的,我是08年开始进入Android这行的,在这期间经历了Android的鼎盛时期,和所谓的Android”凉了“。中间当然也有着,不可说的心酸,看着身边朋友,同事一个个转前端,换行业,其实当时我的心也有过犹豫,但是我还是坚持下来了,这次的疫情就是一个好的机会,大浪淘沙,优胜劣汰。再等等,说不定下一个黄金浪潮就被你等到了。

这是我在这行工作10几年积累的一些资料,如果还想继续在这行业走下去的,或者现在打算跳槽,可以**私信【学习】**我愿意把资料免费分享给大家。
或者直接点击下面链接领取
Android学习PDF+架构视频+面试文档+源码笔记

  • 330页 PDF Android核心笔记

  • 几十套阿里 、字节跳动、腾讯、华为、美团等公司2020年的面试题

  • PDF和思维脑图,包含知识脉络 + 诸多细节

  • Android进阶系统学习视频
    几年积累的一些资料,如果还想继续在这行业走下去的,或者现在打算跳槽,可以**私信【学习】**我愿意把资料免费分享给大家。
    或者直接点击下面链接领取
    Android学习PDF+架构视频+面试文档+源码笔记

  • 330页 PDF Android核心笔记

[外链图片转存中…(img-PHdFiaGz-1710572171161)]

  • 几十套阿里 、字节跳动、腾讯、华为、美团等公司2020年的面试题

[外链图片转存中…(img-n6op2u5U-1710572171162)]

[外链图片转存中…(img-hfoFsBhc-1710572171162)]

  • PDF和思维脑图,包含知识脉络 + 诸多细节

[外链图片转存中…(img-TwEDbpWZ-1710572171163)]

  • Android进阶系统学习视频
  • 18
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值