DYVideoLoadingView.java
8.01 KB
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
package com.wd.common.widget;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import androidx.annotation.Nullable;
import com.wd.fastcoding.base.R;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class DYVideoLoadingView extends View {
private static final String TAG = "DYVideoLoadingView";
private int mWidth, mHeight;
private int mDefaultWidth, mDefaultHeight;
private int mProgressWidth;
private int mMinProgressWidth;
private Paint mPaint;
private String mColor;
private Handler mHandler;
private int mTimePeriod = 1;
public DYVideoLoadingView(Context context) {
this(context, null);
}
public DYVideoLoadingView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public DYVideoLoadingView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
//获取颜色值和最小宽高度,以及进度条最小宽度
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.DYVideoLoadingView);
String color = typedArray.getString(R.styleable.DYVideoLoadingView_amberprogressColor);
mDefaultWidth = (int) typedArray.getDimension(R.styleable.DYVideoLoadingView_amberminWidth, 600);
mDefaultHeight = (int) typedArray.getDimension(R.styleable.DYVideoLoadingView_amberminHeight, 5);
mMinProgressWidth = (int) typedArray.getDimension(R.styleable.DYVideoLoadingView_amberminProgressWidth, 100);
mProgressWidth = mMinProgressWidth;
//根据正则表达式来判断颜色格式是否正确
String regularStr = "^#[A-Fa-f0-9]{6}";
Pattern compile = Pattern.compile(regularStr);
if (color == null) {
mColor = "#808080";
} else {
Matcher matcher = compile.matcher(color);
if (matcher.matches()) {//如果颜色格式正确
mColor = color;
} else {
//如果颜色格式不正确
throw new IllegalArgumentException("wrong color string type!");
}
}
typedArray.recycle();
/* //设置view的默认最小宽度
mDefaultWidth=600;
//设置view的默认最小高度
mDefaultHeight=5;
//设置进度条的初始宽度,这个宽度不能大于view的最小宽度,否则进度条不能向两边延伸
mProgressWidth=100;
//设置默认初始颜色
mColor="#808080";*/
mPaint = new Paint();
//设置虎逼模式为填充带边框
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
//设置抗锯齿
mPaint.setAntiAlias(true);
}
/**
* 设置重绘的周期
*
* @param timePeriod
*/
public void setTimePeriod(int timePeriod) {
if (mTimePeriod > 0) {
this.mTimePeriod = timePeriod;
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//通过widthMeasureSpec,heightMeasureSpec 来获取view的测量模式和宽高
int width = getValue(widthMeasureSpec, true);
int height = getValue(heightMeasureSpec, false);
//此方法用来设置设置View的具体宽高
setMeasuredDimension(width, height);
}
/**
* 获取view的宽高值
*
* @param measureSpec
* @param isWidth 是否是测量宽度
* @return
*/
private int getValue(int measureSpec, boolean isWidth) {
//获取测量模式
int mode = MeasureSpec.getMode(measureSpec);
//获取测量的值
int size = MeasureSpec.getSize(measureSpec);
switch (mode) {
/**
* 如果父控件传递给的MeasureSpec的mode是MeasureSpec.UNSPECIFIED,就说明,父控件对自己没有任何限制,那么尺寸就选择自己需要的尺寸size
如果父控件传递给的MeasureSpec的mode是MeasureSpec.EXACTLY,就说明父控件有明确的要求,希望自己能用measureSpec中的尺寸,这时就推荐使用MeasureSpec.getSize(measureSpec)
如果父控件传递给的MeasureSpec的mode是MeasureSpec.AT_MOST,就说明父控件希望自己不要超出MeasureSpec.getSize(measureSpec),如果超出了,就选择MeasureSpec.getSize(measureSpec),否则用自己想要的尺寸就行了
*/
case MeasureSpec.EXACTLY:
//子view的大小已经被限定死,我们只能使用其固定大小
return size;
case MeasureSpec.AT_MOST:
//父控件认为子view的大小不能超过size的值,那么我们就取size和默认值之间的最小值
return Math.min(isWidth ? mDefaultWidth : mDefaultHeight, size);
case MeasureSpec.UNSPECIFIED:
//父view不限定子view的大小,我们将其值设置为默认值
return isWidth ? mDefaultWidth : mDefaultHeight;
default:
return isWidth ? mDefaultWidth : mDefaultHeight;
}
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mWidth = w;
mHeight = h;
if (mWidth < mProgressWidth) {
//如果宽度小于进度条的宽度
Log.d(TAG, "the progressWidth must less than mWidth");
}
mPaint.setStrokeWidth(mHeight);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//首先判断进度条的宽度是否大于view宽度
if (mProgressWidth < mWidth) {
//如果不大于,将进度条宽度增加10
mProgressWidth += 25;//注意执行此步骤是mProgressWidth值有可能大于view宽度;
} else {
//如果进度条宽度大于view宽度将进度条宽度设置为初始宽度
mProgressWidth = mMinProgressWidth;
}
//计算颜色透明度
//mProgressWidth/mWidth 计算当前进度条宽度占总宽度的比例
//255*mProgressWidth/mWidth 计算当前比例下对应的透明度值
//由于是由不透明变成全透明,所以使用255减去其值
int currentColorValue = 255;
if (mWidth != 0){
currentColorValue = 255 - 255 * mProgressWidth / mWidth;
}
if (currentColorValue > 255) {
//由于mProgressWidth有可能大于view的宽度,要保证颜色值不能大于255
currentColorValue = 255;
}
if (currentColorValue < 30) {
//此处是为了限制让其不成为全透明,如果设置为全透明,在最后阶段进度宽度渐变观察不到
currentColorValue = 30;
}
//将透明度转换为16进制
String s = Integer.toHexString(currentColorValue);
//拼接颜色字符串并转化为颜色值
int color = Color.parseColor("#" + mColor.substring(1, mColor.length()));
//给画笔设置颜色
mPaint.setColor(color);
//使用canvas来画进度条(确实就是画一条线)
canvas.drawLine(mWidth / 2 - mProgressWidth / 2, mDefaultHeight / 2, mWidth / 2 + mProgressWidth / 2,
mDefaultHeight / 2, mPaint);
}
public void startAnimation() {
mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
invalidate();
this.sendEmptyMessageDelayed(1, mTimePeriod);
}
};
mHandler.sendEmptyMessageDelayed(1, mTimePeriod);
}
public void stopAnimation() {
if (mHandler != null) {
mHandler.removeMessages(1);
}
}
}