WaveLoadingIndicator 送出一个波浪进度指示器


github源码地址: https://github.com/liuzhiyi1992/WaveLoadingView

个人博客原文:http://zyden.vicp.cc/waveloadingindicator/
欢迎转载,请注明出处,谢谢

之前在不知道哪里看见有Android的开发者分享一个像是注水玻璃球一样的进度指示器,觉得挺有意思想去了解下实现方式,但是在github上却找不到ios的类似的东西,还是决定自己找个时间尝试尝试实现。原因就是这样,好了先上成品

哈哈还行吧,想玩玩的朋友也可以点appetize.io这里在线运行,进去直接start就可以了。

江湖规矩,控制进度只需控制progress属性就ok了,然后目前demo里可以直接改变波幅和边框宽度来体验,以及正中央的进度提示开关,当然水流速度也可以随心所欲,只是没有开放出来,上面github地址有源码有使用demo,swift的,想怎样改就怎样改。


使用方法:

1.只需要将WaveLoadingIndicator.swift拖进工程里(oc工程可以通过bridge来import)

2.demo中结合SDWebImage演示下载图片进度指示过程(当然适用任何进度指示):


let waveLoadingIndicator: WaveLoadingIndicator = WaveLoadingIndicator(frame: CGRectZero)


使用的时候我把WaveLoadingIndicator加到ImageView里面,并填充整个ImageView,自伸缩

self.displayImageView.addSubview(self.waveLoadingIndicator)  
self.waveLoadingIndicator.frame = self.displayImageView.bounds  
self.waveLoadingIndicator.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]


使用SDWebImage加载网络图片,利用回调里的receivedSize和expectedSize计算已接受比例,对waveLoadingIndicator的progress属性赋值,控制水波的填充度

self.displayImageView.sd_setImageWithURL(url, placeholderImage: nil, options: .CacheMemoryOnly, progress: {
    [weak self](receivedSize, expectedSize) -> Void in

    guard let weakSelf = self else {
        return
    }

    weakSelf.waveLoadingIndicator.progress = Double(CGFloat(receivedSize)/CGFloat(expectedSize))
    }) {
        [weak self](image, error, _, _) -> Void in
        // 不要忘记在完成下载回调中,移除waveLoadingIndicator
        guard let weakSelf = self else {
            return
        }

        weakSelf.waveLoadingIndicator.removeFromSuperview()
}

oc的朋友不必理会里面的guard,不过必须注意防止Block导致的循环引用

swift的朋友平常习惯使用[unowned self]的也要注意了,这里必须使用[weak self],虽然[unowned self]后Block里持有的是弱引用,破坏了循环引用,但如果该controller(self)回收了,unowned机制会导致self变成一个无指向的野指针,SDWebImage再一次回调的时候,crash!

同理,oc的朋友在这种情况下也应使用__weak而不是__unsafe_unretained

对了demo中用的是.CacheMemoryOnly只是为了演示方便,复制的话记得改掉


修改属性,定制个人喜好

点进WaveLoadingIndicator.swift,我们可以按个人需求修改里面的属性:

· cycle —— 循环次数,在控件宽度范围内,该正弦函数图形循环的次数,数值越大,控件范围内看见的正弦函数图形周期数越多,波长约短,波浪也越陡。
· term —— 正弦周期,在layoutSubviews中根据cycle重新计算,==修改无效==
· phasePosition —— 正弦函数相位,==不可修改==,否则图形错乱
· amplitude —— 波幅,数值越大,波浪幅度越大,波浪越陡,反之越平缓,可通过代码调用waveAmplitude修改
· position —— 正弦曲线的X轴 相对于 控件Y坐标的位置,在-drawRect中通过progress计算,==修改无效==
· waveMoveSpan —— 波浪移动的单位跨度,数值越大波浪移动越快,数值过大会出现不连续动画现象
· animationUnitTime —— 重画单位时间,数值越小,重画速度越快频率越大
· heavyColor —— demo中较深的绿色部分
· lightColor —— demo中较浅的绿色部分
· clipCircleColor —— 玻璃球边界颜色
· clipCircleLineWidth —— 玻璃球边线宽度,可通过代码调用borderWidth修改
· progressTextFontSize —— 中央进度提示百分比字号大小


有什么不足或者建议,希望大家在博客评论指出,同时希望大家支持我新建的留言板,谢谢!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在 Android 应用中生成动态波浪,可以使用自定义视图和 ValueAnimator 来实现动画效果。以下是一个简单的实现步骤: 1.创建一个自定义视图,继承自 View 类。 2.在自定义视图中实现一个方法来绘制波浪。 3.在 Activity 中创建一个 ValueAnimator 对象,用于生成动画效果。 4.在 ValueAnimator 的 onAnimationUpdate() 方法中更新波浪的状态,并调用自定义视图的 invalidate() 方法来重绘波浪。 以下是一个简单的实现代码: ``` public class WaveView extends View { private Path path; private Paint paint; private float phase; private float amplitude; private float frequency; public WaveView(Context context) { super(context); init(); } public WaveView(Context context, AttributeSet attrs) { super(context, attrs); init(); } private void init() { path = new Path(); paint = new Paint(); paint.setStyle(Paint.Style.FILL); paint.setColor(Color.BLUE); amplitude = 20; frequency = 1; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); int width = getWidth(); int height = getHeight(); float midY = height / 2f; path.reset(); float x = 0f; float y = 0f; while (x < width) { y = (float) (midY + amplitude * Math.sin(2 * Math.PI * frequency * (x / width) + phase)); if (x == 0) { path.moveTo(x, y); } else { path.lineTo(x, y); } x += 20; } path.lineTo(width, height); path.lineTo(0, height); path.close(); canvas.drawPath(path, paint); } public void setAmplitude(float amplitude) { this.amplitude = amplitude; invalidate(); } public void setFrequency(float frequency) { this.frequency = frequency; invalidate(); } public void setPhase(float phase) { this.phase = phase; invalidate(); } } public class MainActivity extends AppCompatActivity { private WaveView waveView; private ValueAnimator animator; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); waveView = (WaveView) findViewById(R.id.wave_view); animator = ValueAnimator.ofFloat(0f, 1f); animator.setRepeatCount(ValueAnimator.INFINITE); animator.setDuration(2000); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float value = (float) animation.getAnimatedValue(); waveView.setAmplitude(20 + 20 * value); waveView.setFrequency(1 + 2 * value); waveView.setPhase(value * 2 * (float) Math.PI); } }); animator.start(); } @Override protected void onDestroy() { animator.cancel(); super.onDestroy(); } } ``` 在这个例子中,WaveView 类是自定义视图,它负责绘制波浪。MainActivity 类是 Activity,它创建了一个 ValueAnimator 对象并启动了一个线程来更新波浪的状态,并调用 WaveView 类的 invalidate() 方法来重绘波浪。注意,在 onDestroy() 方法中停止 ValueAnimator
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值