WebView 改全屏铺满(与 daoqi msext 同款),撤销 16:9 letterbox

用户反馈:现代 iPhone 横屏(19.5:9 比例)下 16:9 letterbox 出现明显
左右大黑边,与原项目视觉不一致。

调研 daoqi msext NewRootVC.m:256:实际用 CGRectMake(0, 0, DEVW, DEVH)
直接全屏 WKWebView,没有任何 letterbox。H5 viewport 自身处理设计稿
(1280×720)→ 设备实际宽高的伸缩。msext 上线多年用户已习惯此视觉。

改 WebContainerViewController + SubGameViewController 的 setupBridgedWebView:
- 去掉 16:9 aspect 约束 + 居中 + width/height max/fill 优先级方案
- 改为 top/bottom/leading/trailing 四 edge 直接撑满 view

文件头注释同步:从「16:9 letterbox」改为「全屏铺满」。
原 Design §6.3.5 的 letterbox 决策已被现网实测推翻,未来如某些 H5
页面需要恢复 letterbox 再单独抽 LetterboxLayout(YAGNI)。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
joywayer
2026-06-23 07:23:34 +08:00
co-authored by Claude Opus 4.7
parent 4ca4459ad5
commit f4307ccc80
2 changed files with 18 additions and 40 deletions
@@ -2,7 +2,7 @@
// SubGameViewController.swift // SubGameViewController.swift
// ylgamehall // ylgamehall
// //
// 子游戏 H5 承载容器:BridgedWebView + Splash + 16:9 letterbox + boot pipeline。 // 子游戏 H5 承载容器:BridgedWebView 全屏铺满 + Splash + boot pipeline。
// 与 WebContainerViewController(大厅)共享同款 BridgedWebView + SplashOverlay 样式, // 与 WebContainerViewController(大厅)共享同款 BridgedWebView + SplashOverlay 样式,
// 但 boot 流程更短(不拉远端配置、不做 IPA 升级、不做 lobby zip 升级),仅: // 但 boot 流程更短(不拉远端配置、不做 IPA 升级、不做 lobby zip 升级),仅:
// 1) 确保子游戏 H5 已就绪(commit B: SubGameDownloader.ensureReady) // 1) 确保子游戏 H5 已就绪(commit B: SubGameDownloader.ensureReady)
@@ -122,27 +122,18 @@ public final class SubGameViewController: UIViewController {
public override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation { .landscapeRight } public override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation { .landscapeRight }
public override var prefersStatusBarHidden: Bool { false } public override var prefersStatusBarHidden: Bool { false }
// MARK: - 16:9 letterbox(与大厅同款,未来可抽 LetterboxLayout 复用) // MARK: - WebView 全屏布局(与大厅同款,等价 daoqi msext gameController.m
// 全屏 WKWebView 路径)
private func setupBridgedWebView() { private func setupBridgedWebView() {
bridgedWebView.translatesAutoresizingMaskIntoConstraints = false bridgedWebView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(bridgedWebView) view.addSubview(bridgedWebView)
let aspect = bridgedWebView.widthAnchor.constraint(
equalTo: bridgedWebView.heightAnchor,
multiplier: 16.0 / 9.0
)
let widthMax = bridgedWebView.widthAnchor.constraint(lessThanOrEqualTo: view.widthAnchor)
let heightMax = bridgedWebView.heightAnchor.constraint(lessThanOrEqualTo: view.heightAnchor)
let widthFill = bridgedWebView.widthAnchor.constraint(equalTo: view.widthAnchor)
let heightFill = bridgedWebView.heightAnchor.constraint(equalTo: view.heightAnchor)
widthFill.priority = .defaultLow
heightFill.priority = .defaultLow
NSLayoutConstraint.activate([ NSLayoutConstraint.activate([
bridgedWebView.centerXAnchor.constraint(equalTo: view.centerXAnchor), bridgedWebView.topAnchor.constraint(equalTo: view.topAnchor),
bridgedWebView.centerYAnchor.constraint(equalTo: view.centerYAnchor), bridgedWebView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
aspect, widthMax, heightMax, widthFill, heightFill bridgedWebView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
bridgedWebView.trailingAnchor.constraint(equalTo: view.trailingAnchor)
]) ])
} }
@@ -2,7 +2,7 @@
// WebContainerViewController.swift // WebContainerViewController.swift
// ylgamehall // ylgamehall
// //
// H5 大厅承载容器:BridgedWebView 嵌入 + 16:9 letterbox + Splash 覆盖层 // H5 大厅承载容器:BridgedWebView 全屏铺满 + Splash 覆盖层
// + 启动流水线(ensureReady → fetch → resolve → upgrade → loadFileURL)。 // + 启动流水线(ensureReady → fetch → resolve → upgrade → loadFileURL)。
// 详见 docs/H5-Native-Implementation-Design.md §6.3.5。 // 详见 docs/H5-Native-Implementation-Design.md §6.3.5。
// //
@@ -116,37 +116,24 @@ public final class WebContainerViewController: UIViewController {
public override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation { .landscapeRight } public override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation { .landscapeRight }
public override var prefersStatusBarHidden: Bool { false } public override var prefersStatusBarHidden: Bool { false }
// MARK: - 16:9 letterbox 布局 // MARK: - WebView 全屏布局(与 daoqi msext 同款)
// //
// H5 设计分辨率 1280×720(16:9)。设备比例与 16:9 不匹配时用黑边补齐: // 原项目 NewRootVC.m:256 用 `CGRectMake(0, 0, DEVW, DEVH)` 直接全屏铺满 WKWebView,
// - 比 16:9 宽(如现代 iPhone 横屏 2.16:1)→ 左右黑边 // 没有任何 letterbox。H5 viewport 自身处理设计稿(1280×720)→ 设备实际宽高的伸缩。
// - 比 16:9 窄(如 iPad 4:3)→ 上下黑边
// //
// 约束策略: // 早期 ylgamehall 设计文档(§6.3.5)曾用 16:9 letterbox(左右/上下补黑边),但实测
// required:aspect = 16:9,width ≤ view.width,height ≤ view.height // 现代 iPhone 横屏比例约 19.5:9(比 16:9 更宽)→ 左右黑边过大体验差,且偏离 msext
// low: width = view.width,height = view.height(尽量撑满) // 上线多年的视觉习惯。回到与原项目一致的全屏铺满路径。
// 居中: centerX / centerY
// Auto Layout 会自动选择"短边贴边、长边居中"的解。
private func setupBridgedWebView() { private func setupBridgedWebView() {
bridgedWebView.translatesAutoresizingMaskIntoConstraints = false bridgedWebView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(bridgedWebView) view.addSubview(bridgedWebView)
let aspect = bridgedWebView.widthAnchor.constraint(
equalTo: bridgedWebView.heightAnchor,
multiplier: 16.0 / 9.0
)
let widthMax = bridgedWebView.widthAnchor.constraint(lessThanOrEqualTo: view.widthAnchor)
let heightMax = bridgedWebView.heightAnchor.constraint(lessThanOrEqualTo: view.heightAnchor)
let widthFill = bridgedWebView.widthAnchor.constraint(equalTo: view.widthAnchor)
let heightFill = bridgedWebView.heightAnchor.constraint(equalTo: view.heightAnchor)
widthFill.priority = .defaultLow
heightFill.priority = .defaultLow
NSLayoutConstraint.activate([ NSLayoutConstraint.activate([
bridgedWebView.centerXAnchor.constraint(equalTo: view.centerXAnchor), bridgedWebView.topAnchor.constraint(equalTo: view.topAnchor),
bridgedWebView.centerYAnchor.constraint(equalTo: view.centerYAnchor), bridgedWebView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
aspect, widthMax, heightMax, widthFill, heightFill bridgedWebView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
bridgedWebView.trailingAnchor.constraint(equalTo: view.trailingAnchor)
]) ])
} }