【问题标题】:How can I tell WKWebView what layout width to use?如何告诉 WKWebView 使用什么布局宽度?
【发布时间】:2020-07-20 17:24:23
【问题描述】:

我有一些存储在NSData 中的html 内容,我想用WKWebView 显示这些内容。基本上把它想象成ASCII艺术。我遇到的问题是 WKWebView 坚持以这样的方式布置内容,以使其适合 1.0 比例的设备宽度。所以它包裹了很多行文本,使它看起来很糟糕。不管好坏,生成HTML 内容的目的是换行只会在明确的<br> 实例中发生,我无法真正改变这一点。我想要的是能够告诉 WKWebView “将此页面放置为好像屏幕是 1000 像素宽,即使它不是”,然后用户可以水平滚动以查看更长的行(如果需要),或者缩小直到长线适合。

我尝试了很多方法,但都没有任何效果。

  • 我尝试使用 WKWebView 的 framecontentSize(无效)
  • 我尝试更改 WKWebView 的 UIScrollView 的 framecontentSize(无效)
  • 我尝试使用[config.userContentController addUserScript:script] 添加用户脚本。 (在使用 loadDataloadHTMLString 时似乎根本没有真正调用这些。也许它们只能通过 URL 加载?)
  • 尝试在 <meta name='viewport' content='width=2000'> 的 html 字符串本身中添加前导码(这使得视图可以水平滚动到 2000 像素,但 html 内容仍以设备宽度包裹)
  • 尝试将 WKWebView 放在单独的 UIScrollView 中,其中 framecontentSize 设置为比屏幕宽。 (无效)

我可以接受需要在 HTML 本身上附加或附加某些内容的解决方案,但我不希望必须进行 CSS 修改来对文档的内容做出假设。所以像视口元这样的东西很好,但是为特定元素标签添加特殊的 CSS 覆盖并不是那么好(例如,使所有 span 元素成为 display: inline-block;)。如果 iOS API 本身有一种方法可以诱使 WKWebView 在比屏幕更宽的范围内进行布局,那就最好不过了。

设置很简单。我有一个MyUIViewController,它基本上有这段代码来制作 WKWebView 并加载数据。

- (void)viewDidLoad {
  [super viewDidLoad];
  WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
  _webView = [[WKWebView alloc] initWithFrame:frame configuration:config];
  [self.view addSubview:_webView];
  [_webView loadData:_data
                   MIMEType:@"text/html"
      characterEncodingName:@"UTF-8"
                    baseURL:_baseURL];
}

【问题讨论】:

    标签: html ios objective-c wkwebview


    【解决方案1】:

    我认为解决这个问题的(最简单的)方法是在 HTML 方面,但根据您的描述,我不确定这是否可能。您说将其视为 ASCII 艺术,但也不要对文档进行假设的 CSS 更改,因此并不完全清楚。

    如果您将显示的内容嵌入到 codepre 之类的标签中(最简单),或者让 CSS 以您想要的方式破坏它(不太容易),我认为它会解决您的问题。

    那么为什么不把你想显示的东西放到pre呢?

    【讨论】:

      【解决方案2】:

      有很多不同的方法可以接近漂亮的视觉效果。

      A - 用户代理

      您的 webview 伪装成桌面浏览器 (UserAgent),因此负责该浏览器的 CSS 规则而不是移动设备的 CSS 规则。您可以使用下面的代码来更改 UserAgent。但是这个解决方案很不方便,因为它修复了您的 webview 以与 css @media 格式一起使用,而这种格式不适合在较小的屏幕上看到。会弹出与您相反的问题,页面缩放得如此之小,以至于根据您的设备,它们几乎无法正常使用。

      [self.webView setCustomUserAgent:@"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/603.2.4 (KHTML, like Gecko) Version/10.1.1 Safari/603.2.4"];
      

      或相同的想法但不同的方式,你设置你的

      WKWebViewConfiguration::defaultWebpagePreferences: //to another
      
      WKContentMode::preferredContentMode = WKContentModeDesktop;
      

      (没有测试它,如果这有很大帮助并一劳永逸地解决它)

      但您也可以在以下情况下否决作者的比例设置

      WKWebViewConfiguration::(BOOL)ignoresViewportScaleLimits = YES
      

      B - 树解析

      复杂的解决方案,您连接到 html 树 并自己踢出 html 标记框中的 <br>。你最终会编程/使用一个 xml 解析器,其中有很多现有的,即使在 iOS 内部也至少有 3 个不同的现成框架。仅仅了解哪一个最适合您的方案正在消耗您的时间。值得一提的是,HTML 实际上是NSHTMLTextDocumentType,即NSAttributedStringDocumentType,即NSAttributedString,所以也只是NSString,你可以

      NSAttributedString *document = //your document
      [document stringByReplacingOccurrencesOfString:@"<br>" withString:@""];
      

      (问题在于您可能不想解析所有&lt;br&gt;

      D - 注入 js 或 css

      正如你自己提到的,你可以尝试注入一个 cssjs 来解决布局问题。也很复杂并且不适用于所有可能的内容,因为它对于这个特定的网页来说太具体了。一个薄弱的解决方案也是因为网页可能会改变(如果它不是你的)并且所有都必须再次完成,因为它会中断。但你这样做的起点是

      userContentController = [[WKUserContentController alloc] init];
      NSBundle* bundle = [NSBundle bundleForClass:[self class]];
      NSString* scriptLocation = [bundle pathForResource:@"webscreen" ofType:@"js"];
      NSString* scriptSource = [NSString stringWithContentsOfFile:scriptLocation encoding:NSUTF8StringEncoding error:nil];
      WKUserScript* userScript = [[WKUserScript alloc] initWithSource:scriptSource injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES];
      [userContentController addUserScript:userScript];
      [userContentController addScriptMessageHandler:(id<WKScriptMessageHandler>)self name:@"webscreen"];
      config.userContentController = userContentController;
      

      E - resizeSubviews(仅限 macOS)

      您使用(在 iOS 上不可用)[self resizeSubviewsWithOldSize:NSZeroSize]; 调整 UIView 的大小,但我认为您仍然可以以另一种方式在您的内容上使用 CGAffineTransform。这就是它在 macOS 上的样子。类似的东西..

      - (void)resizeSubviewsWithOldSize:(NSSize)oldSize
      {
          CGRect bounds = NSRectToCGRect(self.bounds);
          CGAffineTransform transform = CGAffineTransformIdentity;
          transform = CGAffineTransformScale(transform, 2.0, 2.0);
          CGRect childBounds = CGRectApplyAffineTransform(bounds, transform);
          _webView.frame = childBounds;
      }
      

      F - 将 WKWebView 移动到 UIScrollView

      这可能是控制网页宽度的最快方式,同时让用户可以使用其中的一部分。 移动您的WKWebView 的整个实现UIScrollView 中,并将其而不是“旧”webview 放置在您的 ViewController 中。缺点是,这可能与 HTML 文档的网站缩放和本机滚动行为相冲突。你必须知道什么时候捕捉到哪里,哪些 UIEvents。但如果需要,您也可以告诉这个新的 UIScrollView 进行修复。然后,WebViews 框架可以大于设备的可见 Rect。

      希望对你有一些想法。最后想知道你的解决方案是什么。干杯

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-06-23
        • 2016-11-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-06-03
        相关资源
        最近更新 更多