今天,閒來無事,看到金山詞霸的加載時的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的知識還是非常多的,這些還都是一些皮毛,有機會深入研究,繼續更新。。。。