要实现的功能:
功能 代码流程画贝塞尔曲线:
//画贝塞尔曲线
public class waveView extends View {
private ValueAnimator va;
private Paint mPaint;
private Path mPath;
// 屏幕密度
int density = (int)(getResources().getDisplayMetrics().density);
// 波长
private int waveLength = 200*density;
// 波峰
private int waveCrest = 70*density;
// 动画起始点的偏移值
private int speed;
private int lineColor = Color.BLACK;
private int lineSize = 10;
public waveView(Context context) {
this(context,null);
}
public waveView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(lineColor);
mPaint.setStrokeWidth(lineSize);
mPaint.setStyle(Paint.Style.STROKE);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
startWave();
}
private void startWave(){
va = ValueAnimator.ofInt(0,waveLength);
va.setDuration(500);
va.setRepeatCount(ValueAnimator.INFINITE);
va.setRepeatMode(ValueAnimator.RESTART);
va.setInterpolator(new LinearInterpolator());
va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
// 获取当前值
speed = (int)valueAnimator.getAnimatedValue();
invalidate();
}
});
va.start();
}
public void stopWave(){
if (va != null) {
va.cancel();
}
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mPath = new Path();
// 计算有几个完整的周期
int count = getWidth()/waveLength;
// 设置wave的起始点
mPath.moveTo(-waveLength+speed,getHeight()/2);
// 获取中垂线
int center = (int)getPivotY();
// 确定曲线的路径
for(int start = -waveLength+speed;start < getWidth();start += waveLength){
mPath.cubicTo(start,center,start + waveLength/4,center-waveCrest,start + waveLength/2,center);
mPath.cubicTo(start + waveLength/2,center,start + waveLength*3/4,center+waveCrest,start + waveLength,center);
}
canvas.drawPath(mPath,mPaint);
}
public void setLineColor(int lineColor) {
this.lineColor = lineColor;
mPaint.setColor(lineColor);
}
public void setLineSize(int lineSize) {
this.lineSize = lineSize;
mPaint.setStrokeWidth(lineSize);
}
public void setWaveCrest(int waveCrest) {
this.waveCrest = waveCrest;
}
public void setWaveLength(int waveLength) {
this.waveLength = waveLength;
}
}
画百分数文本和外圈圆环:
public class circleView extends View {
// 控件的外圈
Paint circlePaint;
// 控件的百分数
Paint textPaint;
private int lineWidth = 5;
private int lineColor = Color.BLACK;
private int textColor = Color.GRAY;
private int textSize = 50;
private String text = "100%";
// 百分数的进度
private float progress;
//文字与中心线的距离
private int centerSpace;
public circleView(Context context) {
this(context,null);
}
public circleView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
circlePaint.setColor(lineColor);
circlePaint.setStyle(Paint.Style.STROKE);
circlePaint.setStrokeWidth(lineWidth);
textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
textPaint.setColor(textColor);
textPaint.setStyle(Paint.Style.STROKE);
textPaint.setTextSize(textSize);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int radius = Math.min(getWidth(),getHeight()/2) - 2*lineWidth;
// getPivotX 获取中心点
canvas.drawCircle(getPivotX(),getPivotY(),radius,circlePaint);
text = (int)(progress)+"%";
// 计算文本的宽度
int width = (int) textPaint.measureText(text);
// 获取文字矩阵
Paint.FontMetricsInt fn = textPaint.getFontMetricsInt();
canvas.drawText(text,getPivotX() - width/2,getPivotY() + (-fn.ascent)/2+centerSpace,textPaint);
}
// 定义一系列的setget方法,供外部对控件属性进行设置
public void setLineColor(int lineColor) {
this.lineColor = lineColor;
circlePaint.setColor(lineColor);
}
public void setLineWidth(int lineWidth) {
this.lineWidth = lineWidth;
circlePaint.setStrokeWidth(lineWidth);
}
public void setText(String text) {
this.text = text;
}
public void setTextColor(int textColor) {
this.textColor = textColor;
textPaint.setColor(textColor);
}
public void setTextSize(int textSize) {
this.textSize = textSize;
textPaint.setStrokeWidth(textSize);
}
public void setProgress(float progress) {
this.progress = progress;
if (this.progress >= 100) {
this.progress = 100;
}
invalidate();
}
public float getProgress() {
return progress;
}
public void setCenterSpace(int centerSpace) {
this.centerSpace = centerSpace;
}
}
继承viewGroup承载两个视图:
public class waveLodingView extends ViewGroup {
// 文本的进程
private float progress;
circleView cv;
waveView wv;
public waveLodingView(Context context) {
this(context,null);
}
public waveLodingView(Context context, AttributeSet attrs) {
super(context, attrs);
}
// viewGroup中,通过子视图来确定容器的尺寸(权力大过xml中的布局)
// 1.先调用这个函数测量控件的尺寸
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
// 3.在这里对控件进行布局
// 对所有子视图进行布局
// i:left i1:top i2:right i3:button
@Override
protected void onLayout(boolean b, int i, int i1, int i2, int i3) {
cv = new circleView(getContext());
cv.setLineColor(Color.RED);
cv.setLineWidth(40);
cv.setCenterSpace(-80);
cv.layout(0,0,getWidth(),getHeight());
addView(cv);
wv = new waveView(getContext());
wv.setWaveCrest(30);
wv.setWaveLength(100);
wv.setLineColor(Color.RED);
wv.layout(getWidth()/4,getHeight()/2-30,getWidth()*3/4,getHeight()/2+30);
addView(wv);
}
// 2.在这里控件的尺寸已经确定
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
}
public void setProgress(float progress) {
this.progress = progress;
cv.setProgress(progress);
if (progress >= 100) {
wv.stopWave();
}
}
public float getProgress() {
return progress;
}
}
在xml创建waveLodingView 视图:
<xn.ky.a1027_zdy_1.waveLodingView
android:id="@+id/load"
android:layout_width="300dp"
android:layout_height="300dp"
android:layout_centerInParent="true">
</xn.ky.a1027_zdy_1.waveLodingView>
在MainActivity中实现waveLodingView 的onTouch方法:
public class MainActivity extends AppCompatActivity {
waveLodingView lodingView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lodingView = findViewById(R.id.load);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN){
new Timer().schedule(new TimerTask() {
@Override
public void run() {
runOnUiThread(new Runnable() {
// 将任务抛到主线程
@Override
public void run() {
lodingView.setProgress(lodingView.getProgress() + 5);
}
});
}
},0,100);
}
return true;
}
}
成果展示
网友评论