SweepLoadingView-延时动画-阿里云开发者社区

开发者社区> 开发与运维> 正文
登录阅读全文

SweepLoadingView-延时动画

简介: 这两天写了一个关于延时加载的控件,之前一直是用的 ProgressWheel, 后来参考了 lovejjfg 这个控件设计思路还是很巧妙的。不会用作图工具,凑合着看吧。

这两天写了一个关于延时加载的控件,之前一直是用的 ProgressWheel, 后来参考了 lovejjfg 这个控件设计思路还是很巧妙的。不会用作图工具,凑合着看吧。

SweepLoadingView.png

怎么用?

<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>

效果图

001.gif

奉上源码

<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>

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:
开发与运维
使用钉钉扫一扫加入圈子
+ 订阅

集结各类场景实战经验,助你开发运维畅行无忧

其他文章