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>

目录
相关文章
剪映一秒批量打关键帧
剪映打关键帧, 一百张图片, 只需要一秒钟
1184 0
|
3月前
ThreeJs手动控制动画播放与暂停
这篇文章介绍了如何在Three.js中手动控制动画的播放与暂停,包括设置动画混合器、监听按键事件以调整动画状态和速度的方法。
96 0
ThreeJs手动控制动画播放与暂停
|
7月前
|
图形学
【unity小技巧】最简单的FPS游戏准心跳动动画控制
【unity小技巧】最简单的FPS游戏准心跳动动画控制
64 0
|
XML 图形学 数据格式
Animation组合动画踩坑-实现循环播放动画,可控制次数
Animation组合动画踩坑-实现循环播放动画,可控制次数
动画缓冲 - CAMediaTimingFunction
动画缓冲 - CAMediaTimingFunction
98 0
多个动画次序播放
多个动画次序播放
110 0
SwiftUI—如何修改动画的播放速度和延迟时间
SwiftUI—如何修改动画的播放速度和延迟时间
332 0
|
Web App开发 编解码 JavaScript
如何在VUE中播放RTSP 实时视频,延迟要小于300毫秒?
近期研究在VUE中播放RTSP实时视频,客户要求延迟低于300毫秒,并且要求支持多路同时播放,支持H.265格式视频,比较了下目前市场上常见的几种方案,以供大家参考!
1017 0
如何在VUE中播放RTSP 实时视频,延迟要小于300毫秒?