SwiftUi - 填充宽屏

And*_*can 6 layout aspect-ratio safearealayoutguide swiftui

特尔;博士

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

更新

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

警告讲师

我的假设.scaledToFill可能是错误的。我在最后解决这个问题。

代码

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

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

测试图像

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

测试图像

它标有其子框架,对应于窄(旧)手机 (16:9) 和打击垫 (4:3)。

运行时结果

Xcode 项目设置明确仅限横向,适用于平板电脑和手机。

对于窄手机和所有键盘,上面的代码,观察安全区域,像我期望的那样呈现测试图像:

第一个结果

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

宽电话

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

宽电话

随着对 的调用.edgesIgnoringSafeArea()。我希望这能完全填满屏幕,但它会过度扫描:

在此处输入图片说明

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

在此处输入图片说明

事件顺序

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

ipad 11 失真

解决方法

我认为上述应该有效,我不明白为什么不行。什么的工作-在宽幅手机-是消除了.scaledToFill修改。然后你得到这个。但这只是因为测试图像已经与显示器具有精确的纵横比 - 不是一个非常通用的解决方案。

在此处输入图片说明

缩放以填充

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

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

The*_*d27 2

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

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

更新:这是在没有 GeometryReader 的情况下执行相同操作的另一种方法:

Image("testImage")
    .resizable()
    .scaledToFill()
    .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
    .edgesIgnoringSafeArea(.all)
Run Code Online (Sandbox Code Playgroud)