做程序猿这么久一直没有写博客,是不正常的,故以此为第一篇博客,开始我的博客生涯。

前不久,看到一篇博客,关于X6闪充动画的效果,是一个叫什么“瓶子盖子”写的,暂时就叫这个名字吧,具体名字没记清(sorry)。跑了一下他的代码,发现各种卡顿。。。一查他的代码发现,在死循环里面不停地new Message(),不卡有鬼了。。。当然,我并没有对他有不敬的意思,只是想改良一下效果。

先上vivo X6闪充真机效果图:

充电时会不停地旋转,效果绚丽。

下面讲讲实现原理:

该动画实际上是由四条弧线,和中间的带线条的圆形组成。android里面给了画弧线的方法canvas.drawArc()。这个不难,难的是里面的圆圈带线条。其实“瓶子盖子”的那个方案很不错(给他个赞),画72条线,通过画面的旋转,使得各条线达到对应的位置,下面是代码:

/*** 绘制内切圆和锯齿,通过canvas的旋转,画出对应的锯齿线* @param canvas*/
private void drawCircle(Canvas canvas) {float radius = HEIGHT - (HEIGHT * 0.3f) * 2 - (WIDTH * 0.17f);canvas.drawCircle(WIDTH / 2, HEIGHT / 2, radius, mInCrilePaint);canvas.save();for (int i = 0; i < 72; i++) {if (i >= mProgress) {mInLine.setColor(Color.parseColor("#555555"));} else {mInLine.setColor(Color.parseColor("#00ff00"));}canvas.drawLine(WIDTH / 2, HEIGHT / 3.7f, WIDTH / 2, HEIGHT / 3.7f + HEIGHT * 0.05f , mInLine);canvas.rotate(5, getWidth() / 2, getHeight() / 2);}
}

静态的显示效果出来了,但是还缺少动画效果。“瓶子盖子”的跑动画是通过一个死循环,去跑动画,实现完全可以不用这么做。

安卓里面已经提供了Animator来帮助我们实现动画效果。

事实上,我们可以通过Animator的setRepartCount(-1)来实现无限循环。我猜想,vivo的攻城狮也大致是这样写的吧。

下面贴下代码:

mAnimator = ValueAnimator.ofFloat(0, 1);
mAnimator.setDuration(1500);
mAnimator.setInterpolator(new LinearInterpolator());
mAnimator.setRepeatCount(Animation.INFINITE);
mAnimator.addUpdateListener(this);

整体思路:

1.首先创建一个新的类FlashChargeView继承View,实现动画的监听,以监听到动画变化。在该view的构造方法里,创建一个ValueAnimator,初始化该Animator,使其无限循环播放。提供给外部的只有三个方法:开始播放动画、停止播放动画、设置当前电量。具体代码:

/*** Created by Jxr33 on 2016/8/23.*/
public class FlashChargeView extends View implements ValueAnimator.AnimatorUpdateListener {/** 细线,粗线,圆,圆内进度,文字的画笔 */private Paint mPaintSmall, mPaintBig, mInCrilePaint, mInLine, mTextPaint;/** 控件的高宽 */private static float WIDTH, HEIGHT;/** 动画 */private ValueAnimator mAnimator;/** 圆弧起始角度 */private float startAngle = 0;/** 圆弧旋转角度 */private float offset = 0;/** 当前电量 */private int mCurrPower = 70;/** 当前电量的进度 */private float mProgress;public FlashChargeView(Context context) {super(context);init();}public FlashChargeView(Context context, AttributeSet attrs) {super(context, attrs);init();}public FlashChargeView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init();}private void init() {mPaintSmall = new Paint();mPaintSmall.setAntiAlias(true);mPaintSmall.setStrokeWidth(5);mPaintSmall.setStyle(Paint.Style.STROKE);mPaintSmall.setColor(Color.parseColor("#12ADFF"));mPaintBig = new Paint();mPaintBig.setAntiAlias(true);mPaintBig.setStrokeWidth(20);mPaintBig.setStyle(Paint.Style.STROKE);mPaintBig.setColor(Color.parseColor("#12ADFF"));mInCrilePaint = new Paint();mInCrilePaint.setAntiAlias(true);mInCrilePaint.setStrokeWidth(.5f);mInCrilePaint.setStyle(Paint.Style.STROKE);mInCrilePaint.setColor(Color.parseColor("#eeeeee"));mInLine = new Paint();mInLine.setAntiAlias(true);mInLine.setStrokeWidth(3);mInLine.setColor(Color.parseColor("#00ff00"));mTextPaint = new Paint();mTextPaint.setAntiAlias(true);mTextPaint.setStrokeWidth(3);mTextPaint.setTextSize(80);mTextPaint.setColor(Color.parseColor("#ffffff"));mAnimator = ValueAnimator.ofFloat(0, 1);mAnimator.setDuration(1500);mAnimator.setInterpolator(new LinearInterpolator());mAnimator.setRepeatCount(Animation.INFINITE);mAnimator.addUpdateListener(this);this.mProgress = mCurrPower * 72.0f / 100;}@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);WIDTH = w;HEIGHT = h;}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);drawOutArc1(canvas);drawOutArc2(canvas);drawOutArc3(canvas);drawOutArc4(canvas);drawCircle(canvas);drawCircleIn(canvas);drawText(canvas);}/*** 绘制文字* @param canvas*/private void drawText(Canvas canvas) {float textSize = mTextPaint.measureText(mCurrPower + "%");float x = WIDTH / 2 - textSize / 2;float y = HEIGHT / 2 + textSize / 5;canvas.drawText(mCurrPower + "%", x, y, mTextPaint);}/*** 绘制最里面的圆* @param canvas*/private void drawCircleIn(Canvas canvas) {float radius = (float) (HEIGHT - (HEIGHT * 0.3) * 2 - (WIDTH * 0.22));canvas.drawCircle(WIDTH / 2, HEIGHT / 2, radius, mInCrilePaint);canvas.save();}/*** 绘制内切圆和锯齿,通过canvas的旋转,画出对应的锯齿线* @param canvas*/private void drawCircle(Canvas canvas) {float radius = HEIGHT - (HEIGHT * 0.3f) * 2 - (WIDTH * 0.17f);canvas.drawCircle(WIDTH / 2, HEIGHT / 2, radius, mInCrilePaint);canvas.save();for (int i = 0; i < 72; i++) {if (i >= mProgress) {mInLine.setColor(Color.parseColor("#555555"));} else {mInLine.setColor(Color.parseColor("#00ff00"));}canvas.drawLine(WIDTH / 2, HEIGHT / 3.7f, WIDTH / 2, HEIGHT / 3.7f + HEIGHT * 0.05f , mInLine);canvas.rotate(5, getWidth() / 2, getHeight() / 2);}}/*** 绘制最外层弧线* @param canvas*/private void drawOutArc1(Canvas canvas) {RectF mRectF = new RectF(WIDTH * 0.1f, WIDTH * 0.1f, WIDTH * 0.9f, WIDTH * 0.9f);canvas.drawArc(mRectF, startAngle + offset, 200, false, mPaintSmall);}/*** 绘制外层的第二条弧线* @param canvas*/private void drawOutArc2(Canvas canvas) {RectF mRectF = new RectF(WIDTH * 0.14f, WIDTH * 0.14f, WIDTH * 0.85f, WIDTH * 0.85f);canvas.drawArc(mRectF, -(startAngle + offset), 150, false, mPaintBig);}/*** 绘制外层第三条弧线* @param canvas*/private void drawOutArc3(Canvas canvas) {RectF mRectF = new RectF(WIDTH * 0.22f, WIDTH * 0.22f, WIDTH * 0.795f, WIDTH * 0.795f);canvas.drawArc(mRectF, startAngle + offset - 90, 110, false, mPaintSmall);}/*** 绘制外层第四条弧线* @param canvas*/private void drawOutArc4(Canvas canvas) {RectF mRectF = new RectF(WIDTH * 0.255f, WIDTH * 0.255f, WIDTH * 0.75f, WIDTH * 0.75f);canvas.drawArc(mRectF, -(startAngle + offset + 150), 150, false, mPaintBig);}/*** 开始播放闪充动画*/public void startChargeAnimator() {if (mAnimator != null) {mAnimator.start();}}/*** 停止闪充动画*/public void endChargeAnimator() {if (mAnimator != null) {mAnimator.cancel();}}/*** 设置当前电量* @param power*/public void setPower(int power) {this.mCurrPower = power;this.mProgress = power * 72.0f / 100;}@Overridepublic void onAnimationUpdate(ValueAnimator animation) {float fraction = animation.getAnimatedFraction();this.offset = 360 * fraction;this.invalidate();}
}

2.在布局文件layout里,引用该View:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:background="#000000"tools:context="com.vivo.flashcharge.MainActivity"><com.vivo.flashcharge.FlashChargeViewandroid:id="@+id/chargeView"android:layout_width="180dip"android:layout_height="180dip"android:layout_centerInParent="true"/></RelativeLayout>

3.Activity里引用该layout,并开始播放动画,设置当前电量。(这里用到了ButterKnife插件,该插件封装了findViewById等方法,具体以下再讲):

public class MainActivity extends AppCompatActivity {@BindView(R.id.chargeView)FlashChargeView chargeView;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);ButterKnife.bind(this);chargeView.startChargeAnimator();chargeView.setPower(90);}}

好了,具体效果开发完成了。这里我用的开发工具是Android Studio,很方便很快捷。

最后,得感谢下“瓶子盖”,没有他,我的第一篇博客也不知道要到什么时候才会诞生。估计以后会写更多的博客,大家一块交流嘛~~

Github路径:https://github.com/jxr202/VivoFlashCharge

不积跬步,无以至千里。。。

Android动画——仿vivo X6闪充动画效果相关推荐

  1. 直播app源代码 直播软件开发Android UI动画 仿直播点赞飘心动画效果

    直播app源代码 直播软件开发Android UI动画 仿直播点赞飘心动画效果 一个飘心的小动画,之前看也看到网上有很多轮子,但是感觉不是很符合我的需求,所以自己就凑活凑活搞出来一个,废话不多说先看图 ...

  2. 今日力推: Android 高仿哔哩哔哩动画客户端 / Android MD版的花瓣网App

    一.CardSwipeLayout 仿探探卡片滑动效果的布局 链接: http://pan.baidu.com/s/1qYApDfQ 密码: fz3q 二.Android高仿哔哩哔哩动画客户端bili ...

  3. android 仿 动画,Android动画 - 仿58同城加载动画

    Android动画 - 仿58同城加载动画 效果图 58LoadingView.gif 分析动画 首先分析动画,如上图所示: 动画分为三部分,分别为上方跳动部分,中间阴影部分,和下方文字部分. 上方跳 ...

  4. android 仿qq好友动态,Android UI仿QQ好友列表分组悬浮效果

    本文实例为大家分享了Android UI仿QQ好友列表分组悬浮效果的具体代码,供大家参考,具体内容如下 楼主是在平板上測试的.图片略微有点大,大家看看效果就好 接下来贴源代码: PinnedHeade ...

  5. com.android.vovo,Android仿ViVO X6 极速闪充动画效果

    一直都在看自定义View,经过一个星期的坚持,基本上能够写出一些比较实用的控件效果了,今天天气太热,就待在家里玩手机,然后手机没电了,在充电的时候,看到了手机的充电动画,觉得挺酷,然后自己我就仔细的分 ...

  6. Android 抖音爱心动画,Android动画 - 仿抖音加载动画

    在地铁中刷抖音,由于网络不通畅加载很慢,抖音会加载一个加载动画,感觉很有意思,于是分析了一下,自己写了Demo,实现效果. 效果图 分析动画 首先分析动画,初始状态是由两个相切的圆形图案组成. 将动画 ...

  7. 卷起来了!Android OpenGL仿自如APP裸眼3D效果

    /   今日科技快讯   / 近日,"乘联会"微信公众号发布消息,2021年12月新能源乘用车市场多元化发力,厂商批发销量突破万辆的企业有14家,较前期大幅增多,其中:比亚迪933 ...

  8. Android OpenGL 仿自如 APP 裸眼 3D 效果

    概述 之前看到 自如团队 发布的 自如客APP裸眼3D效果的实现 ,非常有趣,不久后,社区内 Android 的开发者们陆续提供了 Flutter. Android 原生 .Android Jetpa ...

  9. Android实现仿360手机卫士悬浮窗效果

    大家好,今天给大家带来一个仿360手机卫士悬浮窗效果的教程,在开始之前请允许我说几句不相干的废话. 不知不觉我发现自己接触Android已有近三个年头了,期间各种的成长少不了各位高手的帮助,总是有很多 ...

最新文章

  1. 关于并发处理,下列哪些说法符合《阿里巴巴Java开发手册》
  2. poj3565(最大权完美匹配)
  3. 如何像算法工程师一样,看待这个世界?
  4. IDEA显示Run Dashboard窗口,Multiple Spring Boot run configurations were detected. Run Dashboard allows to
  5. 控制面板项 .cpl 文件说明
  6. 计算机控制系统EHA,优·计算机控制技术第四章.doc
  7. 《大数据》再获新荣誉——“综合性人文社会科学”学科最受欢迎期刊
  8. ubuntu 下安装和启动SSH 服务
  9. linux命令五十七之tar命令;linux多个文件压缩打包到一个压缩文件
  10. 黎曼猜想 量子计算机,理解黎曼猜想(一)背景
  11. [论文笔记]Vision-based Control of 3D Facial Animation
  12. 【机器学习百科全书目录】PRML ESL MLAPP 西瓜书 花书 RLAI 统计学习方法 蒲公英书
  13. 【建议背诵】2022下半年软考「高项」100题(2)
  14. python爬虫从企查查获取企业信息-手工绕开企查查的登录验证
  15. 从子窗口中获取父窗口的句柄例子
  16. 安卓手机手电筒不见了?
  17. 1176: 【入门】买蛋糕
  18. 一个著名的调度系统是怎么设计的?
  19. ubuntu系统输入法切换_Ubuntu 安装中文输入法 小白版
  20. 【网络安全】Xss漏洞

热门文章

  1. 老妈,妇女节快乐呀!您辛苦啦!
  2. 第一次认真入门一场ctf比赛
  3. IT行业如何辨别是不是正规无抵押小额贷款
  4. 《Medical image classification using synergic deep learning》论文笔记
  5. Order By文件排序和索引排序
  6. Ubuntu引导修复(Boot Repair)
  7. CakePHP 2.x CookBook 中文版 第七章 模型 之 删除数据
  8. 产品窜货是什么意思?怎么防止窜货行为?
  9. golang后端面试题总结
  10. 【sentinel】流控规则详解