今天,闲来无事,看到金山词霸的加载时的LoadingView甚是不错,于是就小模仿了一下。先看效果:
下面切入正题,先说下思路:
1.确定中心点的座标
2.根据正余弦函数,确定8个小圆的圆心座标
3.定义有8个颜色的数组,画圆的时候依次用不用颜色的画笔
注意:画圆之前要把之前画的圆的颜色置为灰色
下面自定义View的代码:
CircleLoading.java
public class CircleLoading extends View{
private Paint mPaint; //画笔
private Context mContext;
private float mRadius; //小圆半径
private int radius; //大圆半径
private float centerX;
private float centerY;
private int currentPosition = 6; //动画起始位置(即动画从最靠上的那个圆开始)
private boolean isStart = false;
//定义8种颜色
private int colors[] = {Color.YELLOW,Color.GREEN,Color.CYAN,
Color.BLUE,Color.parseColor("#9809F7"),
Color.parseColor("#03F0F7"),Color.RED,
Color.parseColor("#F85004")};
public CircleLoading(Context context) {
this(context,null);
}
public CircleLoading(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public CircleLoading(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
private void init(Context context) {
mContext = context;
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setStyle(Style.FILL);
mPaint.setColor(Color.GRAY);
radius = dip2px(30);
mRadius = dip2px(5);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
//处理 wrap_content问题
int defaultDimension = dip2px(100);
if (widthSpecMode == MeasureSpec.AT_MOST && heightSpecMode == MeasureSpec.AT_MOST) {
setMeasuredDimension(defaultDimension, defaultDimension);
} else if (widthSpecMode == MeasureSpec.AT_MOST) {
setMeasuredDimension(defaultDimension, heightSpecSize);
} else if (heightSpecMode == MeasureSpec.AT_MOST) {
setMeasuredDimension(widthSpecSize, defaultDimension);
}
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
centerX = w/2;
centerY = h/2;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mPaint.setColor(Color.GRAY);
for(int i = 0;i<8;i++){
float circleX = (float) (centerX + radius * Math.cos(Math.PI * i / 4));
float circleY = (float) (centerY + radius * Math.sin(Math.PI *i/4));
canvas.drawCircle(circleX, circleY, mRadius, mPaint);
}
if(isStart){
mPaint.setColor(colors[currentPosition]);
float cx = (float) (centerX + radius * Math.cos(Math.PI * currentPosition / 4));
float cy = (float) (centerY + radius * Math.sin(Math.PI * currentPosition/4));
canvas.drawCircle(cx, cy, mRadius, mPaint);
}
}
//开始动画
public void startAnimator() {
isStart = true;
new Thread(new Runnable() {
@Override
public void run() {
while(true){
Log.i("Main", "currentPosition:"+currentPosition);
postInvalidate();
currentPosition++;
if(currentPosition == 8){
currentPosition = 0;
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
//停止动画
public void stopAnimator() {
isStart = false;
postInvalidate();
}
/**
* 根据手机的分辨率从 dp 的单位 转成为 px(像素)
*/
public int dip2px(float dpValue) {
final float scale = mContext.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
}
接下来是xml文件:
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.sky.view.CircleLoading
android:id="@+id/circle_load"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"/>
</RelativeLayout>
最后是我们的MainActivity:
MainActivity.java
public class MainActivity extends Activity{
private CircleLoading circleLoading;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
circleLoading = (CircleLoading) findViewById(R.id.circle_load);
circleLoading.startAnimator();
}
}
有关自定义View的知识还是非常多的,这些还都是一些皮毛,有机会深入研究,继续更新。。。。