今天网络抽风了,百度时经常看到平时没有注意过的加载动画,因为十分简单,就用自定义view简单实现一下。
老规矩,先上效果图:
可以看到,效果非常简单,就是三个小球的简单运动轨迹。
首先创建自定义view类,并声明需要使用到的变量:
public class BaiduloadingView extends View {
//控件的长、宽
int mWidth, mHeight;
//上下文
Context context;
//小球半径
int radius;
//三支画笔
Paint paint,paint1,paint2;
int degree = 0;
int fegree = 0;
int segree = 0;
int status = 0;
...
}
初始化构造函数
public BaiduloadingView(Context context) {
this(context, null);
}
public BaiduloadingView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public BaiduloadingView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.context = context;
initPaint();
status = dp2px(context,3);
}
初始化三支画笔
private void initPaint() {
paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.RED);
paint.setStrokeWidth(100);
paint.setAntiAlias(true);
paint.setDither(true);
paint1 = new Paint();
paint1.setStyle(Paint.Style.FILL);
paint1.setColor(Color.GREEN);
paint1.setStrokeWidth(100);
paint1.setAntiAlias(true);
paint1.setDither(true);
paint2 = new Paint();
paint2.setStyle(Paint.Style.FILL);
paint2.setColor(Color.BLUE);
paint2.setStrokeWidth(100);
paint2.setAntiAlias(true);
paint2.setDither(true);
}
重写onMeasure方法,在不确定长宽的情况下手动设置。
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int wSize = MeasureSpec.getSize(widthMeasureSpec);
int wMode = MeasureSpec.getMode(widthMeasureSpec);
int hSize = MeasureSpec.getSize(heightMeasureSpec);
int hMode = MeasureSpec.getMode(heightMeasureSpec);
if (wMode == MeasureSpec.EXACTLY) {
mWidth = wSize;
} else {
mWidth = dp2px(context, 250);
}
if (hMode == MeasureSpec.EXACTLY) {
mHeight = hSize;
} else {
mHeight = dp2px(context, 200);
}
setMeasuredDimension(mWidth, mHeight);
}
接下来是核心的onDraw方法。绘制三个小球,核心逻辑有两点:
1.第一个和第三个小球作往返运动,中间小球位置不变。
2.当三个小球交汇时,改变三个小球的颜色。
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
radius = dp2px(context,10);
canvas.drawCircle(radius+degree, mHeight / 2, radius, paint);
canvas.drawCircle(mWidth / 2, mHeight / 2, radius, paint1);
canvas.drawCircle(mWidth - radius+fegree, mHeight / 2, radius, paint2);
degree += status;
fegree -= status;
if(degree <= 0) {
status = dp2px(context,3);
}
if(degree >= mWidth - 2*radius) {
status = -dp2px(context,3);
}
if(Math.abs((mWidth - radius+fegree)-(radius+degree)) <= 10) {
changePaintColor();
}
invalidate();
}
其他的两个方法
/**
* 根据手机的分辨率从 dp 的单位 转成为 px(像素)
*/
public static int dp2px(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
/**
* 更改小球的颜色
*/
private void changePaintColor() {
segree++;
if(segree%3==0) {
paint.setColor(Color.GREEN);
paint1.setColor(Color.BLUE);
paint2.setColor(Color.RED);
}else if(segree%3==1) {
paint.setColor(Color.BLUE);
paint1.setColor(Color.RED);
paint2.setColor(Color.GREEN);
}else {
paint.setColor(Color.RED);
paint1.setColor(Color.GREEN);
paint2.setColor(Color.BLUE);
}
}
整个的逻辑就是这些。使用方法也非常简单,直接在xml文件上配置一下就行了。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.benhuan.mybaiduloadviewdemo.BaiduloadingView
android:layout_centerInParent="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</RelativeLayout>
最后附上完整代码:
package com.benhuan.mybaiduloadviewdemo;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.os.SystemClock;
import android.util.AttributeSet;
import android.view.View;
import java.util.Random;
/**
* Created by Administrator on 2016/12/4.
*/
public class BaiduloadingView extends View {
//控件的长、宽
int mWidth, mHeight;
//上下文
Context context;
//小球半径
int radius;
//三支画笔
Paint paint,paint1,paint2;
int degree = 0;
int fegree = 0;
int segree = 0;
int status = 0;
public BaiduloadingView(Context context) {
this(context, null);
}
public BaiduloadingView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public BaiduloadingView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.context = context;
initPaint();
status = dp2px(context,3);
}
private void initPaint() {
paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.RED);
paint.setStrokeWidth(100);
paint.setAntiAlias(true);
paint.setDither(true);
paint1 = new Paint();
paint1.setStyle(Paint.Style.FILL);
paint1.setColor(Color.GREEN);
paint1.setStrokeWidth(100);
paint1.setAntiAlias(true);
paint1.setDither(true);
paint2 = new Paint();
paint2.setStyle(Paint.Style.FILL);
paint2.setColor(Color.BLUE);
paint2.setStrokeWidth(100);
paint2.setAntiAlias(true);
paint2.setDither(true);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int wSize = MeasureSpec.getSize(widthMeasureSpec);
int wMode = MeasureSpec.getMode(widthMeasureSpec);
int hSize = MeasureSpec.getSize(heightMeasureSpec);
int hMode = MeasureSpec.getMode(heightMeasureSpec);
if (wMode == MeasureSpec.EXACTLY) {
mWidth = wSize;
} else {
mWidth = dp2px(context, 250);
}
if (hMode == MeasureSpec.EXACTLY) {
mHeight = hSize;
} else {
mHeight = dp2px(context, 200);
}
setMeasuredDimension(mWidth, mHeight);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
radius = dp2px(context,10);
canvas.drawCircle(radius+degree, mHeight / 2, radius, paint);
canvas.drawCircle(mWidth / 2, mHeight / 2, radius, paint1);
canvas.drawCircle(mWidth - radius+fegree, mHeight / 2, radius, paint2);
degree += status;
fegree -= status;
if(degree <= 0) {
status = dp2px(context,3);
}
if(degree >= mWidth - 2*radius) {
status = -dp2px(context,3);
}
if(Math.abs((mWidth - radius+fegree)-(radius+degree)) <= 10) {
changePaintColor();
}
invalidate();
}
/**
* 根据手机的分辨率从 dp 的单位 转成为 px(像素)
*/
public static int dp2px(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
/**
* 更改小球的颜色
*/
private void changePaintColor() {
segree++;
if(segree%3==0) {
paint.setColor(Color.GREEN);
paint1.setColor(Color.BLUE);
paint2.setColor(Color.RED);
}else if(segree%3==1) {
paint.setColor(Color.BLUE);
paint1.setColor(Color.RED);
paint2.setColor(Color.GREEN);
}else {
paint.setColor(Color.RED);
paint1.setColor(Color.GREEN);
paint2.setColor(Color.BLUE);
}
}
}