计步器View

不会自定义view的android程序员不是一个好设计,看了QQ运动的的计步view,瞬间萌生了动手仿一个的想法,只要有思路,代码很简单
1.绘背景圆弧
2.绘计步圆弧
3.绘步数
4.绘描述文字
6.设置步数
5:加动画

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
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
/**
* Created by zhangfeng on 2016/10/26.
* 仿计步view
*/
public class StepView extends View {
/**
* 画笔
*/
private Paint paint;
/**
* 背景圆弧所对应的角度
*/
private float arcAngle = 270;
/**
* 圆弧起点角度
*/
private float startlAngle = 135;
/**
* 圆弧画笔宽度
*/
private float paintWidth = 35f;
/**
* 当前所走步数
*/
private int currentStep;
/**
* 当前所走步数文字大小
*/
private float stepTextSize = dipToPx(50);
/**
* 描述文字
*/
private String strText = "步数";
/**
* 描述文字大小
*/
private int describeTextSize = dipToPx(20);
/**
* 当前所走步数对应的弧度
*/
private float currentStepArc;
/**
* 设置滚动的速度
*/
private int aniSpeed = 3000;
public StepView(Context context) {
super(context);
init();
}
public StepView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public StepView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
paint = new Paint();
/**
* 填充样式
* Style.STROKE: 扫边
* Style.FILL: 填充
* FILL_AND_STROKE: 填充加扫边
*/
paint.setStyle(Paint.Style.STROKE);
/**
* 抗锯齿
*/
paint.setAntiAlias(true);
/**
* 画笔宽度
*/
paint.setStrokeWidth(paintWidth);
/**
* 画笔的样式 Paint.Cap.Round: 圆形
* Cap.SQUARE: 方形
*/
paint.setStrokeCap(Paint.Cap.ROUND);
/**
* 结合处为圆弧
*/
paint.setStrokeJoin(Paint.Join.ROUND);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
/**
* 中心点X
*/
float centerX = getWidth() / 2;
/**
* 绘制圆弧所显示的区域
* 参数1: 矩形左边距
* 参数2: 矩形上边距
* 参数3: 矩形右边距
* 参数4: 矩形下边距
*/
RectF rectF = new RectF(paintWidth + 100, paintWidth + 100, centerX * 2 - paintWidth - 100, centerX * 2 - paintWidth - 100);
drawBlueArc(canvas, rectF);
drawRedArc(canvas, rectF);
drawStepNumber(canvas);
drawTipText(canvas);
}
/**
* 绘制蓝色圆弧
*
* @param canvas
* @param rectF
*/
private void drawBlueArc(Canvas canvas, RectF rectF) {
paint.setStyle(Paint.Style.STROKE);
paint.setColor(Color.MAGENTA);
paint.setStrokeWidth(paintWidth);
/**
* 绘制圆弧
* 参数1: 圆弧所在的椭圆对象
* 参数2: 圆弧的起始角度
* 参数3: 圆弧的角度
* 参数4: 是否显示半径连线,true表示显示圆弧与圆心的半径连线,false表示不显示
* 参数5: 画笔
* 如果需绘制270度的圆弧(以本demo为例),圆弧起止点的角度=(360-270)+45 圆弧的绘制方向为顺时针,0度为X轴正方向
*/
canvas.drawArc(rectF, startlAngle, arcAngle, false, paint);
}
/**
* 绘制红色圆弧
*
* @param canvas
* @param rectF
*/
private void drawRedArc(Canvas canvas, RectF rectF) {
paint.setStyle(Paint.Style.STROKE);
paint.setColor(Color.YELLOW);
paint.setStrokeWidth(paintWidth);
canvas.drawArc(rectF, startlAngle, currentStepArc, false, paint);
}
/**
* 绘制当前所走步数
*
* @param canvas
*/
private void drawStepNumber(Canvas canvas) {
paint.setStyle(Paint.Style.FILL);
paint.setStrokeWidth(10);
paint.setColor(Color.WHITE);
paint.setTextSize(stepTextSize);
Rect rect = new Rect();
paint.getTextBounds(currentStep + "", 0, String.valueOf(currentStep).length(), rect);
canvas.drawText(currentStep + "", getWidth() / 2 - rect.width() / 2, getWidth() / 2 + rect.height() / 2, paint);
}
/**
* 绘制描述文字
*
* @param canvas
*/
private void drawTipText(Canvas canvas) {
paint.setStyle(Paint.Style.FILL);
paint.setStrokeWidth(10);
paint.setColor(Color.GRAY);
paint.setTextSize(describeTextSize);
Rect rect = new Rect();
paint.getTextBounds(strText, 0, strText.length(), rect);
canvas.drawText(strText, getWidth() / 2 - rect.width() / 2, getWidth() / 2 + rect.height() + dipToPx(40), paint);
}
/**
* 设置当前所走步数及计划所走步数
*
* @param totalStepValue
* @param currentStepValue
*/
public void setCurrentStep(int currentStepValue, int totalStepValue) {
currentStep = currentStepValue;
if (currentStepValue > totalStepValue) {
currentStepValue = totalStepValue;
}
/**
* 将所走步数转化成弧度
* 算法 :(当前所走步数/总步数)*总弧长
*/
currentStepArc = ((float) currentStepValue / (float) totalStepValue) * arcAngle;
setAinmation(0, currentStepArc, aniSpeed);
}
/**
* 当前走步数加载动画
*
* @param last
* @param current
* @param length
*/
private void setAinmation(float last, float current, int length) {
ValueAnimator valueAnimator = ValueAnimator.ofFloat(last, current);
valueAnimator.setDuration(length);
valueAnimator.setTarget(currentStepArc);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
currentStepArc = (float) animation.getAnimatedValue();
invalidate();
}
});
valueAnimator.start();
}
/**
* 设置文本大小
*
* @param num
*/
public void setTextSize(int num) {
String s = String.valueOf(num);
int length = s.length();
if (length <= 4) {
stepTextSize = dipToPx(50);
} else if (length > 4 && length <= 6) {
stepTextSize = dipToPx(40);
} else if (length > 6 && length <= 8) {
stepTextSize = dipToPx(30);
} else if (length > 8) {
stepTextSize = dipToPx(25);
}
}
/**
* dp 转换成px
*
* @param dip
* @return
*/
private int dipToPx(float dip) {
float density = getContext().getResources().getDisplayMetrics().density;
return (int) (dip * density + 0.5f * (dip >= 0 ? 1 : -1));
}
}


计步view