【问题标题】:SwiftUi - Filling a wide-aspect screenSwiftUi - 填充宽屏
【发布时间】:2020-09-21 16:26:01
【问题描述】:

TL;DR

我无法在宽屏 (13:6) 手机上将图像精确地绘制到全屏上。如果我观察安全区域,则错误是(可以预见的)欠扫描。使用.edgesIgnoringSafeArea()(出乎意料地)在另一个方向上走得太远了。

更新

Apple DTS 建议这是一个错误,向我退还了一次支持事件,并邀请我提交错误报告。它正在https://feedbackassistant.apple.com/feedback/8192204 进行中

告诫讲师

我对@9​​87654337@ 的假设可能是错误的。我在最后解决这个问题。

代码

我可以把它放在这里,它甚至不会减慢你的速度

struct ContentView: View {
    var body: some View {
        Image("testImage").resizable().scaledToFill()
//        .edgesIgnoringSafeArea(.all)
    }
}

测试图片

测试图像是横向矩形,比例为 13:6,与宽手机类似。 (例如 iPhone X 的 812:375 比例。)灰色边缘不是图像的一部分。

它标记了其子帧,对应于窄(旧)电话 (16:9) 和键盘 (4:3)。

运行时结果

Xcode 项目设置明确仅适用于键盘和手机。

对于窄手机和所有平板电脑,上面的代码观察安全区域,按照我的预期呈现测试图像:

但在宽屏手机上,我无法让红色矩形与屏幕边缘重合。

宽屏电话

没有调用.edgesIgnoringSafeArea(),即我们正在观察安全区域。自然地,我们的图像被映射到全屏的一个子集。

通过调用.edgesIgnoringSafeArea()。我预计这会完全填满屏幕,但它会过度扫描:

这是 Xcode 视图层次结构调试器对前一个的看法:图像被映射到比全屏更大 的矩形。为什么?

事件顺序

如果我颠倒修饰符的顺序,并调用.edgesIgnoringSafeArea() 之前 .scaledToFill(),我会得到纵横比失真,.scaledToFill() 应该防止这种情况。 (请参阅屏幕截图中的圆圈变成椭圆。)解释这些操作是如何组成的,以及它们为什么不通勤,可能对回答我的主要问题大有帮助。

解决方法

我认为上述方法应该可行,但我不明白为什么不可行。 在宽屏手机上的作用 是消除.scaledToFill 修饰符。然后你得到这个。但它之所以有效,是因为测试图像已经与显示器的宽高比完全相同——这不是一个非常通用的解决方案。

按比例填充

在风景图像和显示的受限域中,我希望对 13:6 测试图像进​​行缩放填充的操作相当于(具有以下语义):

  1. 在目标(容器)矩形中居中测试图像,大小以完全适合容器。
  • 我一直期待忽略安全区域意味着“目的地”将是全屏,但这可能是我犯错的地方。
  1. 扩大测试图像,保持比例和中心,直到一对边与容器的边重合。
  • 对于较窄的显示器,左右边缘首先会合,顶部和底部将位于目标矩形内。
  1. 但现在不要停下来。这将是缩放以适应,或信箱。
  2. 展开直到您的顶部和底部与容器的顶部和底部重合。
  • 对于较窄的显示器,这意味着两边的内容都会被裁剪
  • 对于 13:6 显示,所有四个图像边缘将同时与显示边缘重合。

【问题讨论】:

    标签: layout swiftui aspect-ratio safearealayoutguide


    【解决方案1】:

    我不知道为什么 .edgesIgnoringSafeArea() 不能正常工作,但这里有一个可以帮助您的解决方法。

        GeometryReader { geo in
           Image("testImage")
              .resizable()
              .scaledToFill()
              .frame(width: geo.size.width, height: geo.size.height)
        }
        .edgesIgnoringSafeArea(.all)
    

    更新: 这是不使用 GeometryReader 的另一种方法:

    Image("testImage")
        .resizable()
        .scaledToFill()
        .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
        .edgesIgnoringSafeArea(.all)
    

    【讨论】:

    • 谢谢,您的两种解决方法都适用于宽屏 (13:6) 手机和平板电脑,除了 对于 11 英寸手机,它顽固地显示为上面我的倒数第二个(事件顺序)屏幕截图。我几乎每天都看到这个错误/错误功能,因为我的应用程序使用全屏背景图像,必须逐个像素地匹配前景对象。我在 6 月 6 日向 Apple 发起了支持事件,除了机器确认之外什么也没听到,而 WWDC 可能直到 7 月才听到。到目前为止,你是积分赢家。
    • 好吧,11英寸iPad的纵横比是10:7,所以给定的纵横比理论上也不适合。
    • 啊哈,我忽略了这一点。你是对的,1194/834 ≈ 10/7(更像是 63/44,但不是什么),而不是 4/3。这解释了 11" 垫上的横向“欠扫描”——这不是一个错误。谢谢!那些数字正盯着我的脸,我看了看但没有读。
    • Apple DTS 建议我对此提交错误报告。是时候用更高分辨率的测试图像重新拍摄所有这些屏幕截图了。