热门标签 | HotTags
当前位置:  开发笔记 > Android > 正文

Android仿ViVOX6极速闪充动画效果

这篇文章主要介绍了Android仿ViVOX6极速闪充动画效果,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

一直都在看自定义View,经过一个星期的坚持,基本上能够写出一些比较实用的控件效果了,今天天气太热,就待在家里玩手机,然后手机没电了,在充电的时候,看到了手机的充电动画,觉得挺酷,然后自己我就仔细的分析了一下这里的动画内容,就觉得,这个我也能写出来,所以就有了这篇博客。纯属原创。

先看看效果,因为图片的原因,只能看到静态的。

这个就是效果图了。当然了,这么看好像不怎么样,但是配上了动画,还是挺好看的。

自定义控件的话,其实做的多了,运用的多了,就会觉得自定义View,跟在Photo shop 里面画图一样,我们通过建立图层,然后再图层里面绘制自己想要的效果。

这里其实也是一样的,运用到了我前面讲的一些知识,比如这篇:
Android自定义View弧线进度控件,原理上大体相当,结合这次的效果,我们看看,这里面是有四个弧形,两个圆,还有一个类似于时钟刻度的效果。所以知道这些的话,这就比较容易实现了。

首先,新建一个类,取名为VIVOPhone,然后继承自View,重载三个构造函数,然后进入主题。

同样的,我们先看看运用到了哪些变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 定义五个画笔
private Paint mSmileRing, mBigRing, mInCrilePaint, mInLine, mTextPaint;
// 控件的高宽
private float mWidth, mHeight;
// 矩形的空间
private RectF mRectF;
// 四个弧线的开始角度
private float startAngle = 270, startAngle2 = 270, startAngle3 = 270,
 startAngle4 = 270, sweepAngle = 90;
// 文字
private String text = "70%";
// 文字的大小
private float tvSize = 80;
// 刻度的进度
private float progress;

然后我们开始初始化数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
private void initView() {
 mSmileRing = new Paint();
 mSmileRing.setAntiAlias(true);
 mSmileRing.setStrokeWidth(5);
 mSmileRing.setStyle(Style.STROKE);
 mSmileRing.setColor(Color.parseColor("#12ADFF"));
 
 mBigRing = new Paint();
 mBigRing.setAntiAlias(true);
 mBigRing.setStrokeWidth(20);
 mBigRing.setStyle(Style.STROKE);
 mBigRing.setColor(Color.parseColor("#12ADFF"));
 
 mInCrilePaint = new Paint();
 mInCrilePaint.setAntiAlias(true);
 mInCrilePaint.setStrokeWidth((float) 0.5);
 mInCrilePaint.setStyle(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(tvSize);
 mTextPaint.setColor(Color.parseColor("#ffffff"));
 }

这里主要是对画笔进行初始化,包括设置大小、宽度、样式、颜色等等。这个方法,最后还是要在构造函数里面调用。

画笔初始化好了,接下来就看看怎么给变量赋值;

一样的,我们还是在onSizeChange()方法里面写赋值的操作。代码如下:

1
2
3
4
5
6
7
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mWidth = w;
mHeight = h;
 
}

这里很简单,就是给高跟宽赋值。

好了,最后看看onDraw方法是怎么写的。

1
2
3
4
5
6
7
8
9
10
11
12
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvasOutArc1(canvas, mRectF);
canvasOutArc2(canvas, mRectF);
canvasOutArc3(canvas, mRectF);
canvasOutArc4(canvas, mRectF);
drawCircle(canvas);
drawCircleIn(canvas);
canvasDrawText(canvas);
 
}

没错,我这里把每一个的绘制都抽成了方法,这样是为了更好的管理和阅读。看到一个:

1
2
3
4
5
6
7
8
9
10
/**
* 绘制最外面的弧线
*
* @param canvas
*/
private void canvasOutArc1(Canvas canvas, RectF mRectF) {
mRectF = new RectF((float) (mWidth * 0.1), (float) (mWidth * 0.1),
 (float) (mWidth * 0.9), (float) (mWidth * 0.9));
canvas.drawArc(mRectF, startAngle, sweepAngle + 90, false, mSmileRing);
}

这个是最外层的圆,接下来就是第二个,第三个,第四个,我全部列出来。

1
2
3
4
5
6
7
8
9
10
11
/**
 * 绘制外层的第二个
 *
 * @param canvas
 * @param mRectF
 */
 private void canvasOutArc2(Canvas canvas, RectF mRectF) {
 mRectF = new RectF((float) (mWidth * 0.14), (float) (mWidth * 0.14),
  (float) (mWidth * 0.85), (float) (mWidth * 0.85));
 canvas.drawArc(mRectF, startAngle2, sweepAngle + 30, false, mBigRing);
 }

第三个:

1
2
3
4
5
6
7
8
9
10
/**
 * 绘制里面第二个小的
 *
 * @param canvas
 */
 private void canvasOutArc3(Canvas canvas, RectF mRectF) {
 mRectF = new RectF((float) (mWidth * 0.22), (float) (mWidth * 0.22),
  (float) (mWidth * 0.795), (float) (mWidth * 0.795));
 canvas.drawArc(mRectF, startAngle3, sweepAngle, false, mSmileRing);
 }

第四个:

1
2
3
4
5
6
7
8
9
10
/**
* 绘制里面第二个小的
*
* @param canvas
*/
private void canvasOutArc4(Canvas canvas, RectF mRectF) {
mRectF = new RectF((float) (mWidth * 0.255), (float) (mWidth * 0.255),
 (float) (mWidth * 0.75), (float) (mWidth * 0.75));
canvas.drawArc(mRectF, startAngle4, sweepAngle, false, mBigRing);
}

然后就是两个圆了:

第一个圆,这里面还包含了锯齿:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// 绘制内切圆和锯齿
 private void drawCircle(Canvas canvas) {
 float radius = (float) (mHeight - (mHeight * 0.3) * 2 - (mWidth * 0.17));
 float yuanX = (float) (mHeight / 2);
 float yuanY = (float) (mWidth / 2);
 
 canvas.drawCircle(yuanX, yuanY, radius, mInCrilePaint);
 canvas.save();
 
 float nowWidth = (float) (getMeasuredWidth());
 float nowHeight = getMeasuredHeight();
 for (int i = 0; i <72; i++) {
  // canvas.drawLine(nowWidth / 2, nowHeight / 2 - nowWidth / 2,
  // nowWidth / 2, nowHeight / 2 - nowWidth / 2 + 30, mInLine);
 
  if (i >= progress) {
  mInLine.setColor(Color.parseColor("#555555"));
  } else {
  mInLine.setColor(Color.parseColor("#00ff00"));
  }
 
  canvas.drawLine(nowWidth / 2,
   (float) (nowHeight / 2 - nowWidth / 2 + mWidth / 3.7),
   nowWidth / 2, (float) (nowHeight / 2 - nowWidth / 2
    + mWidth * 0.05 + mWidth / 3.7), mInLine);
 
  canvas.rotate(5, getWidth() / 2, getHeight() / 2);
 
 }
 
 }

第二个圆:

1
2
3
4
5
6
7
8
9
10
// 绘制最里面的圆
 private void drawCircleIn(Canvas canvas) {
 float radius = (float) (mHeight - (mHeight * 0.3) * 2 - (mWidth * 0.22));
 float yuanX = (float) (mHeight / 2);
 float yuanY = (float) (mWidth / 2);
 
 canvas.drawCircle(yuanX, yuanY, radius, mInCrilePaint);
 canvas.save();
 
 }

最后暴露给外面一个方法,用于动画效果:

1
2
3
4
5
6
7
8
public void setData(int startAngle, float d) {
this.startAngle = startAngle;
this.startAngle2 = 360 - startAngle;
this.startAngle3 = startAngle;
this.startAngle4 = 360 - startAngle;
progress = d / 4;
postInvalidateDelayed(500);
}

这里为了效果更明显,我让它五毫秒的速度更新UI,这里就是View的全部内容,下面,我把所有的代码都列出来:

布局文件:



 


MainActivity.java:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class MainActivity extends Activity {
 private VivoView view;
 private boolean isRun = true;
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);
 view = (VivoView) findViewById(R.id.vivo);
 
 new Thread(new Runnable() {
  public void run() {
  synchronized (view) {
 
   while (isRun) {
   Message msg;
   for (int i = 0; i <n2; i="i" +="" 10)="" {="" msg="new" message();="" msg.obj="i;" systemclock.sleep(100);="" msg.what="1;" handler.sendmessage(msg);="" }="" }).start();="" int="" n2="2;" private="" handler="" handler()="" public="" void="" handlemessage(android.os.message="" msg)="" switch="" (msg.what)="" case="" 1:="" a="(Integer)" msg.obj;="" view.setdata(a,="" a);="" break;="" 2:="" default:="" };="" <="" pre="">
</n2;>

VivoView.java:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
public class VivoView extends View {
 // 定义五个画笔
 private Paint mSmileRing, mBigRing, mInCrilePaint, mInLine, mTextPaint;
 // 控件的高宽
 private float mWidth, mHeight;
 // 矩形的空间
 private RectF mRectF;
 // 四个弧线的开始角度
 private float startAngle = 270, startAngle2 = 270, startAngle3 = 270,
  startAngle4 = 270, sweepAngle = 90;
 // 文字
 private String text = "70%";
 // 文字的大小
 private float tvSize = 80;
 // 刻度的进度
 private float progress;
 
 public VivoView(Context context, AttributeSet attrs, int defStyle) {
 super(context, attrs, defStyle);
 initView();
 
 }
 
 public VivoView(Context context, AttributeSet attrs) {
 super(context, attrs);
 initView();
 }
 
 public VivoView(Context context) {
 super(context);
 initView();
 }
 
 private void initView() {
 mSmileRing = new Paint();
 mSmileRing.setAntiAlias(true);
 mSmileRing.setStrokeWidth(5);
 mSmileRing.setStyle(Style.STROKE);
 mSmileRing.setColor(Color.parseColor("#12ADFF"));
 
 mBigRing = new Paint();
 mBigRing.setAntiAlias(true);
 mBigRing.setStrokeWidth(20);
 mBigRing.setStyle(Style.STROKE);
 mBigRing.setColor(Color.parseColor("#12ADFF"));
 
 mInCrilePaint = new Paint();
 mInCrilePaint.setAntiAlias(true);
 mInCrilePaint.setStrokeWidth((float) 0.5);
 mInCrilePaint.setStyle(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(tvSize);
 mTextPaint.setColor(Color.parseColor("#ffffff"));
 }
 
 @Override
 protected void onSizeChanged(int w, int h, int oldw, int oldh) {
 super.onSizeChanged(w, h, oldw, oldh);
 mWidth = w;
 mHeight = h;
 
 }
 
 @Override
 protected void onDraw(Canvas canvas) {
 super.onDraw(canvas);
 canvasOutArc1(canvas, mRectF);
 canvasOutArc2(canvas, mRectF);
 canvasOutArc3(canvas, mRectF);
 canvasOutArc4(canvas, mRectF);
 drawCircle(canvas);
 drawCircleIn(canvas);
 canvasDrawText(canvas);
 
 }
 
 // 绘制文字
 private void canvasDrawText(Canvas canvas) {
 float textSize = mTextPaint.measureText(text);
 float x = mWidth / 2 - textSize / 2;
 float y = mHeight / 2 + textSize / 5;
 canvas.drawText(text, x, y, mTextPaint);
 }
 
 // 绘制最里面的圆
 // 绘制内切圆和锯齿
 private void drawCircleIn(Canvas canvas) {
 float radius = (float) (mHeight - (mHeight * 0.3) * 2 - (mWidth * 0.22));
 float yuanX = (float) (mHeight / 2);
 float yuanY = (float) (mWidth / 2);
 
 canvas.drawCircle(yuanX, yuanY, radius, mInCrilePaint);
 canvas.save();
 
 }
 
 // 绘制内切圆和锯齿
 private void drawCircle(Canvas canvas) {
 float radius = (float) (mHeight - (mHeight * 0.3) * 2 - (mWidth * 0.17));
 float yuanX = (float) (mHeight / 2);
 float yuanY = (float) (mWidth / 2);
 
 canvas.drawCircle(yuanX, yuanY, radius, mInCrilePaint);
 canvas.save();
 
 float nowWidth = (float) (getMeasuredWidth());
 float nowHeight = getMeasuredHeight();
 for (int i = 0; i <72; i++) {
  // canvas.drawLine(nowWidth / 2, nowHeight / 2 - nowWidth / 2,
  // nowWidth / 2, nowHeight / 2 - nowWidth / 2 + 30, mInLine);
 
  if (i >= progress) {
  mInLine.setColor(Color.parseColor("#555555"));
  } else {
  mInLine.setColor(Color.parseColor("#00ff00"));
  }
 
  canvas.drawLine(nowWidth / 2,
   (float) (nowHeight / 2 - nowWidth / 2 + mWidth / 3.7),
   nowWidth / 2, (float) (nowHeight / 2 - nowWidth / 2
    + mWidth * 0.05 + mWidth / 3.7), mInLine);
 
  canvas.rotate(5, getWidth() / 2, getHeight() / 2);
 
 }
 
 }
 
 /**
 * 绘制最外面的弧线
 *
 * @param canvas
 */
 private void canvasOutArc1(Canvas canvas, RectF mRectF) {
 mRectF = new RectF((float) (mWidth * 0.1), (float) (mWidth * 0.1),
  (float) (mWidth * 0.9), (float) (mWidth * 0.9));
 canvas.drawArc(mRectF, startAngle, sweepAngle + 90, false, mSmileRing);
 }
 
 /**
 * 绘制外层的第二个
 *
 * @param canvas
 * @param mRectF
 */
 private void canvasOutArc2(Canvas canvas, RectF mRectF) {
 mRectF = new RectF((float) (mWidth * 0.14), (float) (mWidth * 0.14),
  (float) (mWidth * 0.85), (float) (mWidth * 0.85));
 canvas.drawArc(mRectF, startAngle2, sweepAngle + 30, false, mBigRing);
 }
 
 /**
 * 绘制里面第二个小的
 *
 * @param canvas
 */
 private void canvasOutArc3(Canvas canvas, RectF mRectF) {
 mRectF = new RectF((float) (mWidth * 0.22), (float) (mWidth * 0.22),
  (float) (mWidth * 0.795), (float) (mWidth * 0.795));
 canvas.drawArc(mRectF, startAngle3, sweepAngle, false, mSmileRing);
 }
 
 /**
 * 绘制里面第二个小的
 *
 * @param canvas
 */
 private void canvasOutArc4(Canvas canvas, RectF mRectF) {
 mRectF = new RectF((float) (mWidth * 0.255), (float) (mWidth * 0.255),
  (float) (mWidth * 0.75), (float) (mWidth * 0.75));
 canvas.drawArc(mRectF, startAngle4, sweepAngle, false, mBigRing);
 }
 
 public void setData(int startAngle, float d) {
 this.startAngle = startAngle;
 this.startAngle2 = 360 - startAngle;
 this.startAngle3 = startAngle;
 this.startAngle4 = 360 - startAngle;
 progress = d / 4;
 postInvalidateDelayed(500);
 }
 
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


推荐阅读
  • Android 九宫格布局详解及实现:人人网应用示例
    本文深入探讨了人人网Android应用中独特的九宫格布局设计,解析其背后的GridView实现原理,并提供详细的代码示例。这种布局方式不仅美观大方,而且在现代Android应用中较为少见,值得开发者借鉴。 ... [详细]
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • Android LED 数字字体的应用与实现
    本文介绍了一种适用于 Android 应用的 LED 数字字体(digital font),并详细描述了其在 UI 设计中的应用场景及其实现方法。这种字体常用于视频、广告倒计时等场景,能够增强视觉效果。 ... [详细]
  • RecyclerView初步学习(一)
    RecyclerView初步学习(一)ReCyclerView提供了一种插件式的编程模式,除了提供ViewHolder缓存模式,还可以自定义动画,分割符,布局样式,相比于传统的ListVi ... [详细]
  • 本文介绍如何在 Android 中通过代码模拟用户的点击和滑动操作,包括参数说明、事件生成及处理逻辑。详细解析了视图(View)对象、坐标偏移量以及不同类型的滑动方式。 ... [详细]
  • 本文探讨了 RESTful API 和传统接口之间的关键差异,解释了为什么 RESTful API 在设计和实现上具有独特的优势。 ... [详细]
  • 本文详细介绍了Java编程语言中的核心概念和常见面试问题,包括集合类、数据结构、线程处理、Java虚拟机(JVM)、HTTP协议以及Git操作等方面的内容。通过深入分析每个主题,帮助读者更好地理解Java的关键特性和最佳实践。 ... [详细]
  • Python自动化处理:从Word文档提取内容并生成带水印的PDF
    本文介绍如何利用Python实现从特定网站下载Word文档,去除水印并添加自定义水印,最终将文档转换为PDF格式。该方法适用于批量处理和自动化需求。 ... [详细]
  • 在当前众多持久层框架中,MyBatis(前身为iBatis)凭借其轻量级、易用性和对SQL的直接支持,成为许多开发者的首选。本文将详细探讨MyBatis的核心概念、设计理念及其优势。 ... [详细]
  • 将Web服务部署到Tomcat
    本文介绍了如何在JDeveloper 12c中创建一个Java项目,并将其打包为Web服务,然后部署到Tomcat服务器。内容涵盖从项目创建、编写Web服务代码、配置相关XML文件到最终的本地部署和验证。 ... [详细]
  • XNA 3.0 游戏编程:从 XML 文件加载数据
    本文介绍如何在 XNA 3.0 游戏项目中从 XML 文件加载数据。我们将探讨如何将 XML 数据序列化为二进制文件,并通过内容管道加载到游戏中。此外,还会涉及自定义类型读取器和写入器的实现。 ... [详细]
  • 本文介绍如何在 Unity 的 XML 配置文件中,将参数传递给自定义生命周期管理器的构造函数。我们将详细探讨 CustomLifetimeManager 类的实现及其配置方法。 ... [详细]
  • 本文详细介绍了 Java 中 org.apache.xmlbeans.SchemaType 类的 getBaseEnumType() 方法,提供了多个代码示例,并解释了其在不同场景下的使用方法。 ... [详细]
  • 本文详细介绍了如何解决MyBatis中常见的BindingException错误,提供了多种排查和修复方法,确保Mapper接口与XML文件的正确配置。 ... [详细]
  • 基于KVM的SRIOV直通配置及性能测试
    SRIOV介绍、VF直通配置,以及包转发率性能测试小慢哥的原创文章,欢迎转载目录?1.SRIOV介绍?2.环境说明?3.开启SRIOV?4.生成VF?5.VF ... [详细]
author-avatar
一枝红杏出墙来2001
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有