首先说一下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,谢谢!