最近項目中遇到一個要求實現(xiàn)類似于安裝軟件過程中的load動畫的需求,就是有幾條短線循環(huán)的水平移動,類似于Progressbar的效果,但是視圖不一樣
GIF.gif
這個效果原生控件ProgressBar是實現(xiàn)不了的,剛好最近再學(xué)習(xí)自定義View,就來小試牛刀一下。
其實實現(xiàn)起來很簡單,連自定義屬性都不需要,我們只需要不斷地重新繪制短線就可以了代碼很簡單,注釋寫的很清楚
package com.meskal;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
/**
* Created by meskal on 2016/9/6.
* Function:
* Version:
*/
public class LoopProgressBar extends View {
//短線的顏色,我們也可以開放一個setColor接口設(shè)置顏色
private int color;
//繪制短線的畫筆
private Paint paint;
//短線之間間隔
private float space;
//短線的寬度
private float lineWidth;
//繪制短線的起點
private int startX;
public LoopProgressBar(Context context) {
this(context, null);
}
public LoopProgressBar(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public LoopProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray ta = context.obtainStyledAttributes(attrs,R.styleable.LoopProgressBar);
if(ta != null){
color = ta.getColor(R.styleable.LoopProgressBar_lineColor, Color.GREEN);
space = ta.getDimension(R.styleable.LoopProgressBar_space, Util.dip2px(20));
lineWidth = ta.getDimension(R.styleable.LoopProgressBar_lineWidth, Util.dip2px(50));
}
if(ta != null){
ta.recycle();
}
paint = new Paint();
paint.setColor(color);
paint.setAntiAlias(true);
}
@Override protected void onDraw(Canvas canvas) {
//整個控件的高度和寬度當(dāng)執(zhí)行到onDraw時已經(jīng)layout了寬高早已經(jīng)測量完成
int w = getMeasuredWidth();
int h = getMeasuredHeight();
//每次重繪短線移動的距離
int delta = 10;
//畫筆的寬度
paint.setStrokeWidth(h);
//startX從0開始每次遞增delta,當(dāng)?shù)谝桓叹€(最右邊一根)的右端到達(dá)空間末尾時從0重新開始繪制,形成循環(huán)
if (startX >= w + (lineWidth + space) - (w % (lineWidth + space))) {
startX = 0;
} else {
startX += delta;
}
float start = startX;
//繪制短線
while (start < w) {
canvas.drawLine(start, 5, start + lineWidth, 5, paint);
start += (lineWidth + space);
}
start = startX - space - lineWidth;
//從左邊進(jìn)入的短線
while (start >= -lineWidth) {
canvas.drawLine(start, 5, start + lineWidth, 5, paint);
start -= (lineWidth + space);
}
//延遲一定的時間重繪,否則太快了,如果要流暢的話1s至少得16幀即62ms一幀,這里設(shè)置為60還挺流暢的
postInvalidateDelayed(60);
}
}
控件的自定義屬性:
<declare-styleable name="LoopProgressBar">
<attr format="color" name="lineColor"/>
<attr format="dimension" name="space"/>
<attr format="dimension" name="lineWidth"/>
</declare-styleable>
具體實現(xiàn)很簡單,沒幾行代碼,主要是計算從什么位置開始繪制短線,特別是當(dāng)?shù)谝桓叹€到最右邊時,一定要減去結(jié)余的那部分
w % (lineWidth + space)
```
這樣保證任何寬度下都很“連貫”