iOS WKWebView高度自适应以及截获页面点击的url

本文介绍了如何使用 UIWebView 和 WKWebView 实现网页内容高度自适应的功能。通过 JavaScript 获取页面的实际高度,并更新 WebView 的尺寸,确保内容完全显示且不出现空白区域。

首先来看下UIWebView的做法:

UIWebView *webView = [[UIWebViewalloc]initWithFrame:CGRectMake(0,0,WIDTH,0)];

webView.delegate =self;

[self.viewaddSubview:webView];

[webView loadHTMLString:html/*html内容*/ baseURL:nil];


-(void)webViewDidFinishLoad:(UIWebView*) webView {


    //获取页面高度,并重置webview的frame

    CGFloat documentHeight = [[webViewstringByEvaluatingJavaScriptFromString:@"document.getElementById(\"content\").offsetHeight;"]floatValue];

    CGRect frame = webView.frame;

    frame.size.height = documentHeight;

    webView.frame = frame;

}


- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {

    

    NSString* strRequest = request.URL.absoluteString;

    

    if([strRequestisEqualToString:@"about:blank"]) {//主页面加载内容

        returnYES;//允许跳转

    } else {//截获页面里面的链接点击

        //do something you want

        returnNO;//不允许跳转

    }

}


在来对应看下WKWebView:

WKWebView   *wkWebview = [[WKWebView allocinitWithFrame:CGRectMake(00WIDTH0)];

wkWebview.navigationDelegate self;

[self.view wkWebview];

[wkWebview loadHTMLString:html/*html内容*/ baseURL:nil];


- (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecifiedWKNavigation *)navigation {

    [webView evaluateJavaScript:@"document.getElementById(\"content\").offsetHeight;"completionHandler:^(id_Nullable result,NSError *_Nullable error) {

//获取页面高度,并重置webview的frame

        CGFloat documentHeight = [resultdoubleValue];

        CGRect frame = webView.frame;

        frame.size.height = documentHeight;

        webView.frame = frame;

    }];

}


// 类似 UIWebView -webView: shouldStartLoadWithRequest: navigationType:

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {

    

    NSString *strRequest = [navigationAction.request.URL.absoluteStringstringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

    if([strRequestisEqualToString:@"about:blank"]) {//主页面加载内容

        decisionHandler(WKNavigationActionPolicyAllow);//允许跳转

    } else {//截获页面里面的链接点击

        //do something you want

decisionHandler(WKNavigationActionPolicyCancel);//不允许跳转

    }

}


高度自适应代码下载链接:http://download.youkuaiyun.com/detail/luco2008/9502733

<think>我们正在讨论的是iOS平台下的WKWebView页面自适应问题。根据用户提供的站内引用和之前Android WebView的讨论,我们可以总结出iOS WKWebView实现页面自适应的几种方法。注意,用户特别提到了引用[1]、[2]、[3]、[4]的内容,我们将结合这些引用进行回答。 在iOS中,WKWebView页面自适应主要涉及两个方面: 1. 页面内容自适应(包括图片、文本等元素的宽度自适应屏幕) 2. WebView高度自适应(根据内容高度动态调整WebView高度) 下面分别介绍: ### 一、页面内容自适应(解决页面显示过小或过大,特别是图片自适应) #### 方法1:通过注入JavaScript添加viewport标签(推荐) 引用[3]提到,当后台没有做手机端适配时,页面可能显示很小。这是因为缺少了viewport标签。我们可以通过注入一个viewport标签来让页面自适应设备宽度。 ```swift // 创建WKWebView时配置 let wkUScript = WKUserScript( source: "var meta = document.createElement('meta'); meta.setAttribute('name', 'viewport'); meta.setAttribute('content', 'width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no'); document.getElementsByTagName('head')[0].appendChild(meta);", injectionTime: .atDocumentEnd, forMainFrameOnly: true ) let wkUController = WKUserContentController() wkUController.addUserScript(wkUScript) let config = WKWebViewConfiguration() config.userContentController = wkUController // 创建WKWebView let webView = WKWebView(frame: self.view.bounds, configuration: config) ``` **原理**:在文档加载结束时,向head中添加一个meta viewport标签,设置内容宽度为设备宽度,并禁止缩放。 #### 方法2:通过CSS样式实现图片自适应 类似于Android方案,我们可以通过注入CSS样式来确保图片等元素的最大宽度不超过设备宽度。 ```swift // 在页面加载完成后注入CSS let cssString = "img { max-width: 100% !important; height: auto !important; }" let jsString = "var style = document.createElement('style'); style.innerHTML = '\(cssString)'; document.head.appendChild(style);" webView.evaluateJavaScript(jsString, completionHandler: nil) ``` 通常,我们可以在`webView(_:didFinish:)`代理方法中执行上述代码。 ### 二、WKWebView高度自适应(根据内容高度调整WebView高度) 引用[2]和[4]提到,可以通过JavaScript获取内容高度,然后调整WebView高度。 #### 步骤: 1. 在页面加载完成后,通过JavaScript获取内容高度。 2. 将获取高度设置给WKWebView的frame或者高度约束。 ```swift // 实现WKNavigationDelegate代理方法 func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { webView.evaluateJavaScript("document.body.scrollHeight") { [weak self] (result, error) in if let height = result as? CGFloat { // 调整webView高度 var frame = webView.frame frame.size.height = height webView.frame = frame // 或者更新高度约束 // self?.webViewHeightConstraint.constant = height } } } ``` **注意**:如果页面内容动态变化(如异步加载),可能需要监听DOM变化并重新计算高度。可以使用以下方法: ```swift // 在页面加载完成后注入监听DOM变化的JavaScript let js = """ window.addEventListener('load', function() { var targetHeight = document.body.scrollHeight; window.webkit.messageHandlers.sizeUpdate.postMessage(targetHeight); }); window.addEventListener('resize', function() { var targetHeight = document.body.scrollHeight; window.webkit.messageHandlers.sizeUpdate.postMessage(targetHeight); }); """ let script = WKUserScript(source: js, injectionTime: .atDocumentEnd, forMainFrameOnly: true) wkUController.addUserScript(script) wkUController.add(self, name: "sizeUpdate") ``` 然后在WKScriptMessageHandler中接收高度变化: ```swift extension YourViewController: WKScriptMessageHandler { func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) { if message.name == "sizeUpdate", let height = message.body as? CGFloat { // 更新高度 webViewHeightConstraint.constant = height self.view.layoutIfNeeded() } } } ``` ### 最佳实践组合 1. **内容自适应**:在初始化WKWebView时注入viewport标签(方法1),并在页面加载完成后注入CSS样式(方法2)确保图片等元素自适应。 2. **高度自适应**:在`didFinish`中获取初始高度,并监听DOM变化动态调整高度。 ### 注意事项 - 如果页面内容包含大量异步加载,高度自适应可能需要多次调整。 - 使用`scrollHeight`获取高度可能包含浮动元素,需要根据实际情况调整。 - 在iOS中,WKWebView的布局要避免与AutoLayout冲突,建议使用约束布局。 ### 示例代码(完整流程) ```swift import UIKit import WebKit class ViewController: UIViewController, WKNavigationDelegate, WKScriptMessageHandler { var webView: WKWebView! override func viewDidLoad() { super.viewDidLoad() // 配置WKWebView let config = WKWebViewConfiguration() let userContentController = WKUserContentController() // 1. 注入viewport标签 let viewportScript = WKUserScript( source: "var meta = document.createElement('meta'); meta.name = 'viewport'; meta.content = 'width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no'; document.getElementsByTagName('head')[0].appendChild(meta);", injectionTime: .atDocumentEnd, forMainFrameOnly: true ) userContentController.addUserScript(viewportScript) // 2. 注入监听高度变化的脚本 let heightScript = WKUserScript( source: """ window.addEventListener('load', function() { var targetHeight = document.body.scrollHeight; window.webkit.messageHandlers.sizeUpdate.postMessage(targetHeight); }); window.addEventListener('resize', function() { var targetHeight = document.body.scrollHeight; window.webkit.messageHandlers.sizeUpdate.postMessage(targetHeight); }); """, injectionTime: .atDocumentEnd, forMainFrameOnly: true ) userContentController.addUserScript(heightScript) userContentController.add(self, name: "sizeUpdate") config.userContentController = userContentController // 创建WebView webView = WKWebView(frame: view.bounds, configuration: config) webView.navigationDelegate = self view.addSubview(webView) // 设置约束(可选) webView.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ webView.topAnchor.constraint(equalTo: view.topAnchor), webView.leadingAnchor.constraint(equalTo: view.leadingAnchor), webView.trailingAnchor.constraint(equalTo: view.trailingAnchor), // 高度先设为0,后面会动态调整 webView.heightAnchor.constraint(equalToConstant: 0) ]) // 加载页面 if let url = URL(string: "https://example.com") { webView.load(URLRequest(url: url)) } } // MARK: - WKNavigationDelegate func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { // 3. 注入CSS样式 let cssString = "img { max-width: 100% !important; height: auto !important; }" let jsString = "var style = document.createElement('style'); style.innerHTML = '\(cssString)'; document.head.appendChild(style);" webView.evaluateJavaScript(jsString, completionHandler: nil) // 获取初始高度(可选,因为监听脚本已经发送) webView.evaluateJavaScript("document.body.scrollHeight") { (result, error) in if let height = result as? CGFloat { // 更新高度约束 self.updateWebViewHeight(height) } } } // MARK: - WKScriptMessageHandler func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) { if message.name == "sizeUpdate", let height = message.body as? CGFloat { updateWebViewHeight(height) } } private func updateWebViewHeight(_ height: CGFloat) { // 更新高度约束 webView.constraints.filter { $0.firstAttribute == .height }.forEach { $0.constant = height } self.view.layoutIfNeeded() } } ``` ### 总结 通过以上方法,我们可以在iOSWKWebView中实现页面内容自适应高度自适应。重点在于: - 注入viewport标签确保页面缩放正确[^3] - 注入CSS样式确保图片等元素自适应宽度 - 通过JavaScript获取内容高度并动态调整WebView高度[^2][^4] §§相关问题§§ 1. 在WKWebView中如何实现视频的自适应? 2. 除了高度,如何实现WKWebView宽度的自适应? 3. WKWebViewiOS不同版本上实现自适应有哪些差异?</think>### iOS WKWebView 页面自适应实现方法 在 iOS 中实现 WKWebView 页面自适应,主要有以下三种核心方法,根据实际需求选择组合使用: #### 方法一:注入 viewport 元标签(最推荐) ```swift // 创建配置时注入 viewport 标签 let viewportScript = WKUserScript( source: """ var meta = document.createElement('meta'); meta.setAttribute('name', 'viewport'); meta.setAttribute('content', 'width=device-width, initial-scale=1.0'); document.getElementsByTagName('head')[0].appendChild(meta); """, injectionTime: .atDocumentEnd, forMainFrameOnly: true ) let userContentController = WKUserContentController() userContentController.addUserScript(viewportScript) let config = WKWebViewConfiguration() config.userContentController = userContentController // 创建 WKWebView webView = WKWebView(frame: view.bounds, configuration: config) ``` **原理**:通过 JavaScript 动态添加 viewport 标签,强制页面按设备宽度渲染[^3]。 **效果**:解决页面显示过小问题,实现基础自适应。 --- #### 方法二:CSS 注入实现元素自适应 ```swift // 在页面加载完成后注入自适应样式 func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { let cssString = """ img, video { max-width: 100% !important; height: auto !important; } body { width: 100% !important; overflow-x: hidden !important; } """ let jsString = """ var style = document.createElement('style'); style.innerHTML = '\(cssString)'; document.head.appendChild(style); """ webView.evaluateJavaScript(jsString) } ``` **关键点**: 1. 图片/视频设置 `max-width: 100%` 防止溢出屏幕 2. Body 设置 `width: 100%` 保证内容宽度适配 3. 添加 `!important` 覆盖原有样式[^3] --- #### 方法三:动态高度自适应(针对嵌入场景) ```swift // 监听内容高度变化 func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { webView.evaluateJavaScript("document.body.scrollHeight") { [weak self] (height, error) in guard let contentHeight = height as? CGFloat else { return } // 更新 WebView 高度约束 self?.webViewHeightConstraint.constant = contentHeight self?.view.layoutIfNeeded() } } // 注册高度变化监听 userContentController.add(self, name: "heightUpdate") ``` ```javascript // 在页面中监听尺寸变化 window.addEventListener('resize', function() { var height = document.body.scrollHeight; window.webkit.messageHandlers.heightUpdate.postMessage(height); }); ``` --- ### 最佳实践组合 ```swift // 配置阶段 let config = WKWebViewConfiguration() let userContentController = WKUserContentController() // 1. 添加 viewport 标签 let viewportScript = WKUserScript(source: viewportJS, injectionTime: .atDocumentEnd, forMainFrameOnly: true) userContentController.addUserScript(viewportScript) // 2. 注册高度监听 userContentController.add(self, name: "heightUpdate") // 3. 加载页面 webView = WKWebView(frame: .zero, configuration: config) webView.navigationDelegate = self // 页面加载完成后 func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { // 4. 注入自适应 CSS injectResponsiveCSS() // 5. 获取初始高度 updateWebViewHeight() } ``` --- ### 注意事项 1. **禁止缩放**(可选): ```swift webView.scrollView.isScrollEnabled = false ``` 2. **处理横竖屏切换**: ```swift override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { webView.reload() // 或重新获取高度 } ``` 3. **兼容特殊元素**: - 表格:添加 `overflow-x: auto` - iframe:设置 `max-width: 100%` > ⚠️ 对于第三方网页,优先使用 CSS 注入方案;对于本地 HTML,推荐直接嵌入 viewport 标签。
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值