摘要
这是一个仿照微信的WebViewProgress,与github上多星的 NJKWebViewProgress 有所区别,有兴趣可以看看。
由来
iOS 与 Android 的区别
最近看到在项目里面的 webview 加载的时候使用菊花图转圈圈,由于iOS的 web 加载机制与 Android 不同:Android 是会等整个页面load完毕再进行显示;而 iOS 并非这样,会一边 load 一边显示。所以设计 iOS 和 Android 一样使用菊花图,反而浪费了 iOS 本身加载的优势。因为我们只能在: webViewDidFinishLoad 方法让菊花图消失,加载网页的过程,菊花图会一直挡住前面,影响我们浏览。
UIWebView 本身的限制
而熟悉iOS开发的的都知道,iOS 的 UIWebView 并没有向我们提供与加载网页进度相关的 API,我们是没有办法得知加载进度的。我们能使用的只有 UIWebViewDelegate 以下几个方法:
1 2 3
| - (void)webViewDidStartLoad:(UIWebView *)webView; - (void)webViewDidFinishLoad:(UIWebView *)webView - (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
|
思路
NJKWebViewProgress 的实现
webViewDidStartLoad 是一个请求的开始,所有的请求都要经过它,未加载资源之前,能够得到一个URL 有多少个资源需要加载,使用_loadingCount++ 方式来计数。
webViewDidFinishLoad、didFailLoadWithError 是一个请求的结束,每次请求结束 _loadingCount –,并重新计数进度,进度使用 _loadingCount/_maxLoadCount 的方式来计算。但是这种做法也是有一定弊端的:进度条经常卡在1/4的地方,然后突然启动加载完毕,有点不流畅。
我猜测的wechat的做法
我们在平时使用wechat时,会发现即使你网络很差,甚至是没有网络的时候,加载的进度条还是会一直走到达末端停止,最后超时才显示网络故障;这样无疑会给用户较好的体验,毕竟进度条一直走,即使网页没有在加载,我们也会以为他一直在加载,很安心的feel。
我的做法
我参考了wechat的做法,写了一个加速度的三次递减的进度条。
把进度条设置为 1000,初始化为100,各个阶段的递增值如下:
- 0 ~ 500: 每 100ms 增加 50
- 500 ~ 700: 每 100ms 增加 20
- 700 ~ 800: 每 100ms 增加 15
- 800 ~ 920: 每 100ms 增加 1
- 920 :卡住等待超时
用到 GCD 的延时循环加载。具体可查看代码。
效果图
网络正常
网络不正常
使用
导入头文件
1
| #import "LZProgresSHeader.h"
|
需要对象
1 2
| LZWebViewProgressView *_progressView; LZWebViewProgress *_progressProxy;
|
具体代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
| #import "ViewController.h" #import "LZProgresSHeader.h"
@interface ViewController ()<UIWebViewDelegate,LZWebViewProgressDelegate>
@property (weak, nonatomic) IBOutlet UIWebView *webView;
@end
@implementation ViewController { LZWebViewProgressView *_progressView; LZWebViewProgress *_progressProxy; }
- (void)viewDidLoad { [super viewDidLoad]; self.automaticallyAdjustsScrollViewInsets = NO;
_progressProxy = [[LZWebViewProgress alloc] init]; _webView.delegate = _progressProxy; _progressProxy.webViewProxyDelegate = self; _progressProxy.progressDelegate = self; CGFloat progressBarHeight = 2.f; CGRect navigationBarBounds = self.navigationController.navigationBar.bounds; CGRect barFrame = CGRectMake(0, navigationBarBounds.size.height - progressBarHeight, navigationBarBounds.size.width, progressBarHeight); _progressView = [[LZWebViewProgressView alloc] initWithFrame:barFrame]; _progressView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin; NSURLRequest *req = [[NSURLRequest alloc] initWithURL:[NSURL URLWithString:@"http://www.bilibili.com"]]; [self.webView loadRequest:req];
}
- (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; }
- (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; [self.navigationController.navigationBar addSubview:_progressView]; }
-(void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; [_progressView removeFromSuperview]; }
#pragma mark - NJKWebViewProgressDelegate -(void)webViewProgress:(LZWebViewProgress *)webViewProgress updateProgress:(float)progress { [_progressView setProgress:progress]; }
@end
|
具体可查看我的 demo 实现。
源码地址
这里面的 LZWebViewProgress 文件是需要导入的SDK; WechatWebViewProgressDemo 是上面我写的使用演示demo。
github链接
最后的话
今天!剪了!最帅!的!短!头发!