1.画流动的波浪
1.MainActivity
public class MainActivity extends AppCompatActivity {
WaveLoadingView loadingView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// loadingView =findViewById(R.id.load);
}
2.xml配置
3. WavaView
public class WavaView extends View {
private Paint mpaint;
private Path mpath;
ValueAnimator va;
float density = getResources().getDisplayMetrics().density;
private int WaveLength = (int) ((int) 80 * density);
private int WaveCrest = (int) (50 * density);
private int speed;//
private int LineColor=Color.BLACK;//线条颜色
private int LineSize=10;//线条粗细
public WavaView(Context context) {
super(context);
init();
}
public WavaView(Context context, AttributeSet attrs) {
super(context, attrs);
//从xml中获取自定义属性的值
initAttr(context,attrs);
//初始化画笔
init();
}
//初始化画笔
private void init() {
mpaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mpaint.setColor(Color.BLACK);
mpaint.setStrokeWidth(10);
mpaint.setStyle(Paint.Style.STROKE);
}
private void initAttr(Context context, AttributeSet attrs){
//读取所有的自定义属性的值
TypedArray array= context.obtainStyledAttributes(attrs,R.styleable.WavaView);
//读取每一个属性的值
WaveLength=array.getInteger(R.styleable.WavaView_WaveLength, (int) (100*density));
WaveCrest=array.getInteger(R.styleable.WavaView_WaveCrest, (int) (50*density));
LineColor=array.getColor(R.styleable.WavaView_LineColor,Color.BLACK);
LineSize=array.getInteger(R.styleable.WavaView_LineSize,10);
}
/**
* 父容器会按照自己的规划给出一个方案
* 子View通过MeasureSpec.getMode .getSize获取对应的模式和具体尺寸
* getMode:
* Unspecified 无限制的 父容器没有对这个控件进行约束
* At_Most 不能超过最大值 (wrap_content)
* Exactly 确定的值(200dp)
*
* @param widthMeasureSpec
* @param heightMeasureSpec
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
/*
//取出宽度的模式和预告尺寸
int mode= MeasureSpec.getMode(widthMeasureSpec);
int width=MeasureSpec.getSize(widthMeasureSpec);
switch(mode){
case MeasureSpec.UNSPECIFIED:
System.out.println("unspecified:"+width);
break;
case MeasureSpec.AT_MOST:
System.out.println("at_most:"+width);
break;
case MeasureSpec.EXACTLY:
System.out.println("exactly:"+width);
break;
}*/
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
startWave();
}
public void stopWave(){
//开始暂停动画
if(va!=null){
va.cancel();
}
}
private void startWave() {
va = ValueAnimator.ofInt(0, WaveLength);
va.setDuration(300);
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();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);//创建曲线
mpath = new Path();
inipath();
canvas.drawPath(mpath, mpaint);
}
//初始化路径
private void inipath() {
//创建曲线
mpath = new Path();
//计算有几个周期(有几个完整的波)
int count = getWidth() / WaveLength;
//设置起始点
mpath.moveTo(0, getHeight() / 2);
//获取垂直中心的坐标
int centerY = (int) getPivotY();
//确定曲线的路径
for (int start = -WaveLength + speed; start < getWidth(); start += WaveLength) {
//画上半周期
mpath.cubicTo(start, centerY, start + WaveLength / 4,
centerY - WaveCrest, start + WaveLength / 2, centerY);
//画下半周期
mpath.cubicTo(start + WaveLength / 2, centerY,
start + WaveLength * 3 / 4, centerY + WaveCrest, start + WaveLength, centerY);
}
}
public int getLineColor() {
return LineColor;
}
public void setLineColor(int lineColor) {
LineColor = lineColor;
mpaint.setColor(LineColor);
}
public int getLineSize() {
return LineSize;
}
public void setLineSize(int lineSize) {
LineSize = lineSize;
mpaint.setStrokeWidth(LineSize);
}
public void setWaveCrest(int waveCrest) {
WaveCrest = waveCrest;
}
public void setWaveLength(int waveLength) {
WaveLength = waveLength;
}
}
2.画圆
1.xml
-->
2. MainActivity
public class MainActivity extends AppCompatActivity {
WaveLoadingView loadingView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// loadingView =findViewById(R.id.load);
}
3. CircleView
public class CircleView extends View {
Paint CirclePaint;
Paint textPaint;
private int centerYspace;//和中心线的距离
private int LineSize=10;
private int LineColor=Color.BLACK;//线条颜色
private int textColor=Color.BLACK;//文本颜色
private int textSize=50;//文本尺寸
private float progress;//进度
public CircleView(Context context) {
super(context);
init();
}
private void init() {
CirclePaint=new Paint(Paint.ANTI_ALIAS_FLAG);
CirclePaint.setColor(LineColor);
CirclePaint.setStrokeWidth(LineSize);
CirclePaint.setStyle(Paint.Style.STROKE);
textPaint=new Paint(Paint.ANTI_ALIAS_FLAG);
textPaint.setColor(textColor);
textPaint.setTextSize(textSize);
}
public CircleView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
@Override
protected void onDraw(Canvas canvas) {
//确定半径
int radius=Math.min(getWidth(),getHeight()/2-2*LineSize);
//画圆
canvas.drawCircle(getPivotX(),getPivotY(),radius,CirclePaint);
//画文本
String text=(int)(progress*100)+"%";
//计算文本宽度
int width= (int) textPaint.measureText(text);
//获取文字fontMetrics
Paint.FontMetricsInt fm= textPaint.getFontMetricsInt();
canvas.drawText(text,getPivotX()-width/2,getPivotY()+(-fm.ascent/2)-centerYspace,textPaint);
}
public void setLineColor(int lineColor) {
LineColor = lineColor;
CirclePaint.setColor(lineColor);
}
public void setLineSize(int lineSize) {
LineSize = lineSize;
CirclePaint.setStrokeWidth(lineSize);
}
public void setTextColor(int textColor) {
this.textColor = textColor;
textPaint.setColor(textColor);
}
public void setTextSize(int textSize) {
this.textSize = textSize;
textPaint.setTextSize(textSize);
}
public float getProgress() {
return progress;
}
public void setProgress(float progress) {
this.progress = progress;
//刷新
invalidate();
}
public int getCenterYspace() {
return centerYspace;
}
public void setCenterYspace(int centerYspace) {
this.centerYspace = centerYspace;
}
}
3.圆和波浪的结合
1.xml
2.WaveLoadingView
public class WaveLoadingView extends ViewGroup {
CircleView cv;
private WavaView wv;
private float progress=0;
public WaveLoadingView(Context context) {
super(context);
}
public WaveLoadingView(Context context, AttributeSet attrs) {
super(context, attrs);
}
/**
*ViewGroup中 通过测量左右子视图来确定容器的宽高
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
}
/**
*对所有子控件进行布局
* b
* i==l left
* i1=t top
* i2=r right
* i3=b bottom
*/
@Override
protected void onLayout(boolean b, int i, int i1, int i2, int i3) {
//创建CircleView
cv = new CircleView(getContext());
cv.setLineColor(Color.RED);
cv.setLineSize(40);
cv.setTextColor(Color.RED);
cv.setCenterYspace(90);
//对子视图进行控局
cv.layout(0, 0, getWidth(), getHeight());
//将子视图添加到容器中
addView(cv);
//创建WaveView
wv = new WavaView(getContext());
wv.setLineColor(Color.RED);
wv.setLineSize(5);
wv.setWaveCrest(50);
wv.setWaveLength(100);
//布局
wv.layout(getWidth() / 4, getHeight() / 2 - 30, getWidth() * 3 / 4, getHeight() / 2 + 30);
addView(wv);
}
public float getProgress() {
return progress;
}
public void setProgress(float progress) {
this.progress = progress;
if(progress<1.001) {
cv.setProgress(progress);
}
if ((int) progress==1){
wv.stopWave();
}
}
}
3.MainActivity
public class MainActivity extends AppCompatActivity {
WaveLoadingView loadingView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
loadingView =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() {
loadingView.setProgress((float) (loadingView.getProgress()+0.01));
}
},0,100);
}
return true;
}
}
4.心得
在昨天的基础上了解学习了ViewGroup的使用