iOS自定义封装控件iOS开发iOS学习笔记

iOS使用CAShapeLayer做一个WebView浏览器进度

2017-01-05  本文已影响629人  九剑仙

首先说一下NJKWebViewProgress,很好很强大,网上用的人也很多,并且是根据“已加载网页资源的个数/要加载网页资源的总个数",展示真实的加载进度。。

但是<神转折>,我们项目中大多数进行网页展示的地方,都是简单的html页面加载。这种页面最大的特点就是--简单,总资源个数往往--等!于!1!

而NJKWebViewProgress只有三个值,0.1,0.5和0.9,这样一来,没网的时候加载进度一直卡在0.1,有网的时候往往瞬间就加载完成,用户体验太差!

再来看UC和微信等浏览器,即便是没网的情况下,进度条也能加载,由此可见,很多浏览器的进度条都并非真实进度,而是模拟的。

既然是模拟的,那就好办了,实现的方式有很多,但是如何才能效率高、性能好呢?

网上有很多大神使用CAShapeLayer做圆形进度条,于是,我把它掰直了。。。。

思路可以分为3部分:1、进度条按一定增长速度匀速增长到0.95,之后增长速度大幅度减慢,网页加载结束后,进度设置为1.0;

2、如果网页加载结束后,所用的加载时间小于0.35秒,采用延时调用,等待0.25秒之后再将进度设为1.0,避免了进度条瞬间跳到1.0,优化用户体验;

3、动画开始和动画结束的时机。

废话不多说了,直接上图上代码,附上github下载地址:https://github.com/wangzhaomeng/LLWebBrowser.git

#import@interface LLWebProgressLayer : CAShapeLayer

- (void)startLoad;

- (void)finishedLoad;

@end

#import "LLWebProgressLayer.h"

static NSTimeInterval const LLFastTimeInterval = 0.01;

@implementation LLWebProgressLayer{

CAShapeLayer *_layer;

NSTimer *_timer;

NSTimeInterval _loadTime;

}

- (id)init {

self = [super init];

if (self) {

self.lineWidth = 2;

self.strokeColor = [UIColor blueColor].CGColor;

UIBezierPath *path = [UIBezierPath bezierPath];

[path moveToPoint:CGPointMake(0, 2)];

[path addLineToPoint:CGPointMake(SCREEN_WIDTH, 2)];

self.path = path.CGPath;

self.strokeEnd = 0;

}

return self;

}

//开始加载动画

- (void)startLoad {

_loadTime = 0.0;

[self LL_SetStrokeEnd:0];

if (!_timer) {

_timer = [NSTimer scheduledTimerWithTimeInterval:LLFastTimeInterval

target:self

selector:@selector(pathChanged:)

userInfo:nil

repeats:YES];

}

}

- (void)pathChanged:(NSTimer *)timer {

if (self.strokeEnd < 0.8) {

self.strokeEnd += 0.01;

}

else if (self.strokeEnd < 0.95){

self.strokeEnd += 0.002;

}

_loadTime += LLFastTimeInterval;

}

//结束加载动画

- (void)finishedLoad {

if (_loadTime < 0.35) {

dispatch_after(dispatch_time(DISPATCH_TIME_NOW,(int64_t)(0.25*NSEC_PER_SEC)),

dispatch_get_main_queue(),^{

[self finished];

});

}

else{

[self finished];

}

}

- (void)finished{

[self closeTimer];

self.strokeEnd = 1.0;

dispatch_after(dispatch_time(DISPATCH_TIME_NOW,(int64_t)(0.25*NSEC_PER_SEC)),

dispatch_get_main_queue(),^{

[self LL_SetStrokeEnd:0];

});

}

- (void)closeTimer {

if (_timer) {

[_timer invalidate];

_timer = nil;

}

}

//无动画

- (void)LL_SetStrokeEnd:(CGFloat)strokeEnd{

if (strokeEnd < self.strokeEnd) {

[CATransaction begin];

[CATransaction setDisableActions:YES];

self.strokeEnd = strokeEnd;

[CATransaction setDisableActions:NO];

[CATransaction commit];

}

}

- (void)removeFromSuperlayer{

[self closeTimer];

[self LL_SetStrokeEnd:0];

[super removeFromSuperlayer];

}

@end

然后在webView代理中,开始加载的时候,开始动画;加载结束或出错的时候,结束动画。

觉得好,请给个star,谢谢!

上一篇 下一篇

猜你喜欢

热点阅读