这两天写了一个关于延时加载的控件,之前一直是用的 ProgressWheel, 后来参考了 lovejjfg 这个控件设计思路还是很巧妙的。不会用作图工具,凑合着看吧。
怎么用?
<pre>
<github.alex.sweeploadingview.SweepLoadingView
xmlns:SweepLoadingView="http://schemas.android.com/apk/res-auto"
android:layout_width="112dp"
android:layout_height="112dp"
android:layout_centerHorizontal="true"
android:layout_marginTop="72dp"
SweepLoadingView:slv_circleColor="#795548"
SweepLoadingView:slv_circleWidth="8dp"
SweepLoadingView:slv_duration="1200"
SweepLoadingView:slv_gapAngle="30"
SweepLoadingView:slv_strokeCap="square" />
</pre>
效果图
<pre>
package github.alex.sweeploadingview;
/**
* 作者:Alex
*
* 时间:2016/8/24 16:31
*
* 博客地址:http://www.jianshu.com/users/c3c4ea133871/subscriptions
*
*
*/
public class SweepLoadingView extends View {
private RectF rectF;
private Paint paint;
private int circleColor;
private int circleWidth;
private int strokeCap;
/**
* 扫描一周 需要的时间
*/
private int swipeDuration;
/**
* 起点的角度
*/
private float startAngle;
/**
* 扫描的角度
*/
private float sweepAngle;
/\*\*
\* 终点 和 起点的间隔 角度
\*/
private float gapAngle;
/\*\*
\* 起始点的偏移量
\*/
private float startAngleOffset;
private ObjectAnimator sweepObjectAnimator;
private ObjectAnimator startAngleObjectAnimator;
/\*\*
\* 扫描一周
\*/
private boolean isSweepRepeat;
public SweepLoadingView(Context context) {
super(context);
initView(null);
}
public SweepLoadingView(Context context, AttributeSet attrs) {
super(context, attrs);
initView(attrs);
}
private void initView(AttributeSet attrs) {
startAngleOffset = 0;
isSweepRepeat = false;
initObjectAnimation();
}
private void initObjectAnimation() {
sweepObjectAnimator = ObjectAnimator.ofFloat(this, new AngleProperty(Float.class, "sweepAngle"), 360F - gapAngle \* 2);
sweepObjectAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
sweepObjectAnimator.setDuration(swipeDuration);
sweepObjectAnimator.setRepeatCount(Integer.MAX_VALUE);
sweepObjectAnimator.setRepeatMode(ValueAnimator.RESTART);
sweepObjectAnimator.addListener(new SweepAngleAnimatorListener());
startAngleObjectAnimator = ObjectAnimator.ofFloat(this, new AngleProperty(Float.class, "startAngle"), 360F);
startAngleObjectAnimator.setInterpolator(new LinearInterpolator());
startAngleObjectAnimator.setDuration(1500);
startAngleObjectAnimator.setRepeatCount(Integer.MAX_VALUE);
startAngleObjectAnimator.setRepeatMode(ValueAnimator.RESTART);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
int min = Math.min(w, h);
int dWidth = circleWidth / 2;
rectF.left = dWidth;
rectF.right = min - dWidth;
rectF.top = dWidth;
rectF.bottom = min - dWidth;
}
@Override
public void draw(Canvas canvas) {
super.draw(canvas);
canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG));
float startAngle = this.startAngle - startAngleOffset;
float sweepAngle = this.sweepAngle;
if (isSweepRepeat) {
startAngle += sweepAngle;
sweepAngle = 360 - sweepAngle - gapAngle;
} else {
sweepAngle += gapAngle;
}
canvas.drawArc(rectF, startAngle, sweepAngle, false, paint);
}
private void startSweepAnimation() {
if (!sweepObjectAnimator.isStarted()) {
LogUtil.e("开始");
sweepObjectAnimator.start();
}
if (!startAngleObjectAnimator.isStarted()) {
startAngleObjectAnimator.start();
}
}
private void stopSweepAnimation() {
LogUtil.e("停止");
sweepObjectAnimator.cancel();
startAngleObjectAnimator.cancel();
}
private final class SweepAngleAnimatorListener extends SimpleAnimatorListener {
@Override
public void onAnimationRepeat(Animator animation) {
handleSweepRepeat();
}
}
/\*\*
\* 处理扫描一周的 情况
\*/
private void handleSweepRepeat() {
if (isSweepRepeat) {
startAngleOffset = (startAngleOffset + gapAngle \* 2) % 360;
}
isSweepRepeat = !isSweepRepeat;
}
private final class AngleProperty extends Property<SweepLoadingView, Float> {
private String name;
public AngleProperty(Class<Float> type, String name) {
super(type, name);
this.name = name;
}
@Override
public Float get(SweepLoadingView object) {
if ("sweepAngle".equals(name)) {
return object.getSweepAngle();
} else {
return object.getStartAngle();
}
}
@Override
public void set(SweepLoadingView object, Float value) {
if ("sweepAngle".equals(name)) {
object.setSweepAngle(value);
} else {
object.setStartAngle(value);
}
}
}
private float getSweepAngle() {
return sweepAngle;
}
private void setSweepAngle(float sweepAngle) {
this.sweepAngle = sweepAngle;
invalidate();
}
private float getStartAngle() {
return startAngle;
}
private void setStartAngle(float startAngle) {
this.startAngle = startAngle;
invalidate();
}
}
</pre>