Commit 2ef7bbf0a21e70c280611f9493c06984a26849cd
1 parent
1db03f45
no message
Showing
4 changed files
with
258 additions
and
0 deletions
CNLiveCustomControl.podspec
| @@ -48,6 +48,11 @@ TODO: 网家家-自定义控件. | @@ -48,6 +48,11 @@ TODO: 网家家-自定义控件. | ||
| 48 | ss.dependency 'CNLiveCategory' | 48 | ss.dependency 'CNLiveCategory' |
| 49 | end | 49 | end |
| 50 | 50 | ||
| 51 | + s.subspec 'WebView' do |ss| | ||
| 52 | + ss.source_files = 'CNLiveCustomControl/Classes/WebView/*' | ||
| 53 | + ss.dependency 'CNLiveTripartiteManagement/QMUIKit' | ||
| 54 | + end | ||
| 55 | + | ||
| 51 | # s.resource_bundles = { | 56 | # s.resource_bundles = { |
| 52 | # 'CNLiveCustomControl' => ['CNLiveCustomControl/Assets/*.png'] | 57 | # 'CNLiveCustomControl' => ['CNLiveCustomControl/Assets/*.png'] |
| 53 | # } | 58 | # } |
CNLiveCustomControl/Classes/CNLiveCustomControl.h
CNLiveCustomControl/Classes/WebView/CNLiveWebView.h
0 → 100755
| 1 | +// | ||
| 2 | +// CNLiveWebView.h | ||
| 3 | +// CNLiveBaseClass | ||
| 4 | +// | ||
| 5 | +// Created by CNLive-zxw on 2019/9/12. | ||
| 6 | +// Copyright © 2019 153993236@qq.com. All rights reserved. | ||
| 7 | +// | ||
| 8 | + | ||
| 9 | +/* | ||
| 10 | + * 自定义WebView | ||
| 11 | + */ | ||
| 12 | + | ||
| 13 | +#import <UIKit/UIKit.h> | ||
| 14 | +#import <WebKit/WebKit.h> | ||
| 15 | + | ||
| 16 | +NS_ASSUME_NONNULL_BEGIN | ||
| 17 | +@class CNLiveWebView; | ||
| 18 | + | ||
| 19 | +@protocol CNLiveWebViewDelegate <NSObject> | ||
| 20 | +@optional | ||
| 21 | +/** 页面开始加载时调用 */ | ||
| 22 | +- (void)webViewDidStartLoad:(CNLiveWebView *)webView; | ||
| 23 | +/** 内容开始返回时调用 */ | ||
| 24 | +- (void)webView:(CNLiveWebView *)webView didCommitWithURL:(NSURL *)url; | ||
| 25 | +/** 页面加载失败时调用 */ | ||
| 26 | +- (void)webView:(CNLiveWebView *)webView didFinishLoadWithURL:(NSURL *)url; | ||
| 27 | +/** 页面加载完成之后调用 */ | ||
| 28 | +- (void)webView:(CNLiveWebView *)webView didFailLoadWithError:(NSError *)error; | ||
| 29 | + | ||
| 30 | +@end | ||
| 31 | + | ||
| 32 | +@interface CNLiveWebView : UIView | ||
| 33 | +@property (nonatomic, strong) WKWebView *wkWebView; | ||
| 34 | +@property (nonatomic, strong) UIProgressView *progressView; | ||
| 35 | + | ||
| 36 | +/** CNLiveWebViewDelegate */ | ||
| 37 | +@property (nonatomic, weak) id<CNLiveWebViewDelegate> delegate; | ||
| 38 | +/** 进度条颜色(默认蓝色) */ | ||
| 39 | +@property (nonatomic, strong) UIColor *progressViewColor; | ||
| 40 | +/** 导航栏标题 */ | ||
| 41 | +@property (nonatomic, copy) NSString *title; | ||
| 42 | + | ||
| 43 | +@property (nonatomic, readonly) BOOL canGoBack; | ||
| 44 | +/** 向后 */ | ||
| 45 | +- (nullable WKNavigation *)goBack; | ||
| 46 | + | ||
| 47 | +@property (nonatomic, readonly) BOOL canGoForward; | ||
| 48 | +/** 向前 */ | ||
| 49 | +- (nullable WKNavigation *)goForward; | ||
| 50 | +/** 刷新数据 */ | ||
| 51 | +- (void)reloadData; | ||
| 52 | + | ||
| 53 | +/** 类方法创建 XWWebView */ | ||
| 54 | ++ (instancetype)webViewWithFrame:(CGRect)frame; | ||
| 55 | +/** 加载 web */ | ||
| 56 | +- (void)loadRequest:(NSURLRequest *)request; | ||
| 57 | +/** 加载 HTML */ | ||
| 58 | +- (void)loadHTMLString:(NSString *)HTMLString; | ||
| 59 | + | ||
| 60 | +@end | ||
| 61 | +NS_ASSUME_NONNULL_END |
CNLiveCustomControl/Classes/WebView/CNLiveWebView.m
0 → 100755
| 1 | +// | ||
| 2 | +// CNLiveWebView.h | ||
| 3 | +// CNLiveBaseClass | ||
| 4 | +// | ||
| 5 | +// Created by CNLive-zxw on 2019/9/12. | ||
| 6 | +// Copyright © 2019 153993236@qq.com. All rights reserved. | ||
| 7 | +// | ||
| 8 | + | ||
| 9 | +#import "CNLiveWebView.h" | ||
| 10 | +#import "QMUIKit.h" | ||
| 11 | + | ||
| 12 | +@interface CNLiveWebView () <WKNavigationDelegate, WKUIDelegate> | ||
| 13 | + | ||
| 14 | +@end | ||
| 15 | + | ||
| 16 | +@implementation CNLiveWebView | ||
| 17 | +static CGFloat const progressViewHeight = 1; | ||
| 18 | + | ||
| 19 | +#pragma mark - 初始化 | ||
| 20 | +- (instancetype)initWithFrame:(CGRect)frame { | ||
| 21 | + if (self = [super initWithFrame:frame]) { | ||
| 22 | + if (@available(iOS 11, *)) { | ||
| 23 | + self.wkWebView.scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentAutomatic; | ||
| 24 | + } | ||
| 25 | + [self addSubview:self.progressView]; | ||
| 26 | + [self addSubview:self.wkWebView]; | ||
| 27 | + } | ||
| 28 | + return self; | ||
| 29 | +} | ||
| 30 | + | ||
| 31 | ++ (instancetype)webViewWithFrame:(CGRect)frame { | ||
| 32 | + return [[self alloc] initWithFrame:frame]; | ||
| 33 | +} | ||
| 34 | + | ||
| 35 | +// dealloc | ||
| 36 | +- (void)dealloc { | ||
| 37 | + [_wkWebView stopLoading]; | ||
| 38 | + [_wkWebView removeObserver:self forKeyPath:NSStringFromSelector(@selector(estimatedProgress))]; | ||
| 39 | + _wkWebView.navigationDelegate = nil; | ||
| 40 | + _wkWebView = nil; | ||
| 41 | +} | ||
| 42 | + | ||
| 43 | +#pragma mark - Setter方法 | ||
| 44 | +- (void)setProgressViewColor:(UIColor *)progressViewColor { | ||
| 45 | + _progressViewColor = progressViewColor; | ||
| 46 | + if (progressViewColor) { | ||
| 47 | + _progressView.tintColor = progressViewColor; | ||
| 48 | + } | ||
| 49 | +} | ||
| 50 | + | ||
| 51 | +#pragma mark - Getter方法 | ||
| 52 | +- (BOOL)canGoBack{ | ||
| 53 | + return self.wkWebView.goBack; | ||
| 54 | +} | ||
| 55 | + | ||
| 56 | +- (BOOL)canGoForward{ | ||
| 57 | + return self.wkWebView.canGoForward; | ||
| 58 | +} | ||
| 59 | + | ||
| 60 | +#pragma mark - 工具方法 | ||
| 61 | +// 向后 | ||
| 62 | +- (nullable WKNavigation *)goBack{ | ||
| 63 | + return [self.wkWebView goBack]; | ||
| 64 | +} | ||
| 65 | +// 向前 | ||
| 66 | +- (nullable WKNavigation *)goForward{ | ||
| 67 | + return [self.wkWebView goForward]; | ||
| 68 | +} | ||
| 69 | +// 刷新数据 | ||
| 70 | +- (void)reloadData { | ||
| 71 | + [self.wkWebView reload]; | ||
| 72 | +} | ||
| 73 | +// 加载 web | ||
| 74 | +- (void)loadRequest:(NSURLRequest *)request { | ||
| 75 | + [self.wkWebView loadRequest:request]; | ||
| 76 | +} | ||
| 77 | +// 加载 HTML | ||
| 78 | +- (void)loadHTMLString:(NSString *)HTMLString { | ||
| 79 | + [self.wkWebView loadHTMLString:HTMLString baseURL:nil]; | ||
| 80 | +} | ||
| 81 | + | ||
| 82 | +#pragma mark - KVO | ||
| 83 | +- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context { | ||
| 84 | + if ([keyPath isEqualToString:NSStringFromSelector(@selector(estimatedProgress))] && object == self.wkWebView) { | ||
| 85 | + self.progressView.alpha = 1.0; | ||
| 86 | + BOOL animated = self.wkWebView.estimatedProgress > self.progressView.progress; | ||
| 87 | + [self.progressView setProgress:self.wkWebView.estimatedProgress animated:animated]; | ||
| 88 | + if(self.wkWebView.estimatedProgress >= 0.97) { | ||
| 89 | + [UIView animateWithDuration:0.1 delay:0.3 options:UIViewAnimationOptionCurveEaseOut animations:^{ | ||
| 90 | + self.progressView.alpha = 0.0; | ||
| 91 | + } completion:^(BOOL finished) { | ||
| 92 | + [self.progressView setProgress:0.0 animated:NO]; | ||
| 93 | + }]; | ||
| 94 | + } | ||
| 95 | + } else { | ||
| 96 | + [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; | ||
| 97 | + } | ||
| 98 | +} | ||
| 99 | + | ||
| 100 | +#pragma mark - WKNavigationDelegate | ||
| 101 | +// 在发送请求之前,决定是否跳转 | ||
| 102 | +- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{ | ||
| 103 | + //允许跳转 | ||
| 104 | + decisionHandler(WKNavigationActionPolicyAllow); | ||
| 105 | +} | ||
| 106 | +// 在收到响应后,决定是否跳转 | ||
| 107 | +- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler{ | ||
| 108 | + //允许跳转 | ||
| 109 | + decisionHandler(WKNavigationResponsePolicyAllow); | ||
| 110 | + //不允许跳转 | ||
| 111 | + //decisionHandler(WKNavigationResponsePolicyCancel); | ||
| 112 | +} | ||
| 113 | +// 页面开始加载时调用 | ||
| 114 | +- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation { | ||
| 115 | + if (self.delegate && [self.delegate respondsToSelector:@selector(webViewDidStartLoad:)]) { | ||
| 116 | + [self.delegate webViewDidStartLoad:self]; | ||
| 117 | + } | ||
| 118 | +} | ||
| 119 | +// 当内容开始返回时调用 | ||
| 120 | +- (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation { | ||
| 121 | + if (self.delegate && [self.delegate respondsToSelector:@selector(webView:didCommitWithURL:)]) { | ||
| 122 | + [self.delegate webView:self didCommitWithURL:self.wkWebView.URL]; | ||
| 123 | + } | ||
| 124 | +} | ||
| 125 | +// 页面加载完成之后调用 | ||
| 126 | +- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation { | ||
| 127 | + if(!self.title){ | ||
| 128 | + self.title = self.wkWebView.title; | ||
| 129 | + } | ||
| 130 | + if (self.delegate && [self.delegate respondsToSelector:@selector(webView:didFinishLoadWithURL:)]) { | ||
| 131 | + [self.delegate webView:self didFinishLoadWithURL:self.wkWebView.URL]; | ||
| 132 | + } | ||
| 133 | + self.progressView.alpha = 0.0; | ||
| 134 | +} | ||
| 135 | +// 页面加载失败时调用 | ||
| 136 | +- (void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error { | ||
| 137 | + if (self.delegate && [self.delegate respondsToSelector:@selector(webView:didFailLoadWithError:)]) { | ||
| 138 | + [self.delegate webView:self didFailLoadWithError:error]; | ||
| 139 | + } | ||
| 140 | + self.progressView.alpha = 0.0; | ||
| 141 | +} | ||
| 142 | +// 页面加载失败时调用 | ||
| 143 | +- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(null_unspecified WKNavigation *)navigation withError:(nonnull NSError *)error{ | ||
| 144 | + if (self.delegate && [self.delegate respondsToSelector:@selector(webView:didFailLoadWithError:)]) { | ||
| 145 | + [self.delegate webView:self didFailLoadWithError:error]; | ||
| 146 | + } | ||
| 147 | + self.progressView.alpha = 0.0; | ||
| 148 | +} | ||
| 149 | +// 接收到服务器跳转请求之后调用(重定向) | ||
| 150 | +- (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation{ | ||
| 151 | + | ||
| 152 | +} | ||
| 153 | + | ||
| 154 | +#pragma mark - 懒加载 | ||
| 155 | +- (WKWebView *)wkWebView { | ||
| 156 | + if (!_wkWebView) { | ||
| 157 | + NSMutableString *javascript = [NSMutableString string]; | ||
| 158 | + [javascript appendString:@"document.documentElement.style.webkitTouchCallout='none';"];//禁止长按 | ||
| 159 | + [javascript appendString:@"document.documentElement.style.webkitUserSelect='none';"];//禁止选择 | ||
| 160 | + WKUserScript *noneSelectScript = [[WKUserScript alloc] initWithSource:javascript injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:YES]; | ||
| 161 | + WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init]; | ||
| 162 | + configuration.allowsInlineMediaPlayback = YES; | ||
| 163 | + WKPreferences *preferences = [WKPreferences new]; | ||
| 164 | + //很重要,如果没有设置这个则不会回调createWebViewWithConfiguration方法,也不会回应window.open()方法 | ||
| 165 | + preferences.javaScriptCanOpenWindowsAutomatically = YES; | ||
| 166 | + configuration.preferences = preferences; | ||
| 167 | + _wkWebView = [[WKWebView alloc] initWithFrame:CGRectMake(0, progressViewHeight, self.frame.size.width, self.frame.size.height-progressViewHeight) configuration:configuration]; | ||
| 168 | + [_wkWebView.configuration.userContentController addUserScript:noneSelectScript]; | ||
| 169 | + _wkWebView.allowsLinkPreview = NO; | ||
| 170 | + _wkWebView.UIDelegate = self; | ||
| 171 | + _wkWebView.navigationDelegate = self; | ||
| 172 | + [_wkWebView addObserver:self forKeyPath:NSStringFromSelector(@selector(estimatedProgress)) options:0 context:nil]; | ||
| 173 | + } | ||
| 174 | + return _wkWebView; | ||
| 175 | +} | ||
| 176 | + | ||
| 177 | +- (UIProgressView *)progressView { | ||
| 178 | + if (!_progressView) { | ||
| 179 | + _progressView = [[UIProgressView alloc] initWithProgressViewStyle:UIProgressViewStyleDefault]; | ||
| 180 | + _progressView.trackTintColor = [UIColor clearColor]; | ||
| 181 | + // 高度默认有导航栏且有穿透效果 | ||
| 182 | + _progressView.frame = CGRectMake(0, 0, self.frame.size.width, progressViewHeight); | ||
| 183 | + // 设置进度条颜色 | ||
| 184 | + _progressView.tintColor = [UIColor colorWithRed:19/255.0 green:204/255.0 blue:12/255.0 alpha:1.0]; | ||
| 185 | + _progressView.progressTintColor = [UIColor colorWithRed:19/255.0 green:204/255.0 blue:12/255.0 alpha:1.0]; | ||
| 186 | + } | ||
| 187 | + return _progressView; | ||
| 188 | +} | ||
| 189 | + | ||
| 190 | +@end |