SwiftUi - 填充宽屏
SwiftUi - Filling a wide-aspect screen
TL;DR:
我无法在宽屏 (13:6) phone 上准确地将图像绘制到全屏上。如果我观察安全区域,错误是(可以预见的)欠扫描。使用 .edgesIgnoringSafeArea()
在另一个方向上(出乎意料地)走得太远了。
更新
Apple DTS 已建议这是一个错误,向我退还了一次支持事件,并邀请我提交错误报告。它在 https://feedbackassistant.apple.com/feedback/8192204
的管道中
告诫讲师
我对 .scaledToFill
的推测可能是错误的。我在最后解决这个问题。
代码
太基础了,我可以把它放在这里,它甚至不会减慢你的速度
struct ContentView: View {
var body: some View {
Image("testImage").resizable().scaledToFill()
// .edgesIgnoringSafeArea(.all)
}
}
测试图片
测试图像是横向矩形,比例为 13:6,与宽 phone 相同。 (例如812:375原始iPhone X的比例。)灰色外围不是图像的一部分。
它的子帧已标记,对应于窄(旧)phones (16:9) 和垫 (4:3)。
运行时结果
对于 pad 和 phones,Xcode 项目设置明确仅限横向。
对于窄 phones 和所有 pad,上面的代码,观察安全区域,像我期望的那样渲染测试图像:
但是在宽 phones 上,我无法让红色矩形与屏幕边缘重合。
宽屏手机
没有调用.edgesIgnoringSafeArea()
,即我们正在观察安全区域。自然地,我们的图像被映射到全屏的一个子集。
用调用.edgesIgnoringSafeArea()
。我希望它能完全填满屏幕,但它会过扫描:
这是 Xcode 视图层次调试器对上一个的看法:图像被映射到比全屏 大 的矩形。为什么?
事件顺序
如果我颠倒修饰符的顺序,并在.scaledToFill()
之前调用.edgesIgnoringSafeArea()
,我会得到宽高比失真,.scaledToFill()
是应该防止。 (请参阅屏幕截图中的圆圈变成椭圆形。)解释这些操作的组成方式以及它们为什么不通勤,可能对回答我的主要问题有很大帮助。
解决方法
我认为以上应该可行,但我不明白为什么不行。 在宽 phone 上的作用是消除 .scaledToFill
修饰符。然后你明白了。但它之所以有效,是因为测试图像 已经 与显示器的确切宽高比——不是一个非常通用的解决方案。
缩放填充
在风景图像和显示的受限域中,我希望 13:6 测试图像上的缩放填充操作等同于(具有以下语义):
- 在目标(容器)矩形中居中测试图像,大小完全适合容器。
- 我一直以为忽略安全区域意味着“目的地”将是全屏,但这可能是我犯错的地方。
- 扩大测试图像,保持比例和中心,直到一对边与容器的边重合。
- 对于较窄的显示,左右边缘将首先相遇,顶部和底部将在目标矩形内。
- 但不要现在停下来。那将是适合的比例,或信箱。
- 展开直到顶部和底部与容器的顶部和底部重合。
- 对于较窄的显示器,这意味着两侧的内容都会被裁剪
- 对于13:6显示,所有四个图像边缘将同时与显示边缘重合。
我不知道为什么 .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)
TL;DR:
我无法在宽屏 (13:6) phone 上准确地将图像绘制到全屏上。如果我观察安全区域,错误是(可以预见的)欠扫描。使用 .edgesIgnoringSafeArea()
在另一个方向上(出乎意料地)走得太远了。
更新
Apple DTS 已建议这是一个错误,向我退还了一次支持事件,并邀请我提交错误报告。它在 https://feedbackassistant.apple.com/feedback/8192204
的管道中告诫讲师
我对 .scaledToFill
的推测可能是错误的。我在最后解决这个问题。
代码
太基础了,我可以把它放在这里,它甚至不会减慢你的速度
struct ContentView: View {
var body: some View {
Image("testImage").resizable().scaledToFill()
// .edgesIgnoringSafeArea(.all)
}
}
测试图片
测试图像是横向矩形,比例为 13:6,与宽 phone 相同。 (例如812:375原始iPhone X的比例。)灰色外围不是图像的一部分。
它的子帧已标记,对应于窄(旧)phones (16:9) 和垫 (4:3)。
运行时结果
对于 pad 和 phones,Xcode 项目设置明确仅限横向。
对于窄 phones 和所有 pad,上面的代码,观察安全区域,像我期望的那样渲染测试图像:
但是在宽 phones 上,我无法让红色矩形与屏幕边缘重合。
宽屏手机
没有调用.edgesIgnoringSafeArea()
,即我们正在观察安全区域。自然地,我们的图像被映射到全屏的一个子集。
用调用.edgesIgnoringSafeArea()
。我希望它能完全填满屏幕,但它会过扫描:
这是 Xcode 视图层次调试器对上一个的看法:图像被映射到比全屏 大 的矩形。为什么?
事件顺序
如果我颠倒修饰符的顺序,并在.scaledToFill()
之前调用.edgesIgnoringSafeArea()
,我会得到宽高比失真,.scaledToFill()
是应该防止。 (请参阅屏幕截图中的圆圈变成椭圆形。)解释这些操作的组成方式以及它们为什么不通勤,可能对回答我的主要问题有很大帮助。
解决方法
我认为以上应该可行,但我不明白为什么不行。 在宽 phone 上的作用是消除 .scaledToFill
修饰符。然后你明白了。但它之所以有效,是因为测试图像 已经 与显示器的确切宽高比——不是一个非常通用的解决方案。
缩放填充
在风景图像和显示的受限域中,我希望 13:6 测试图像上的缩放填充操作等同于(具有以下语义):
- 在目标(容器)矩形中居中测试图像,大小完全适合容器。
- 我一直以为忽略安全区域意味着“目的地”将是全屏,但这可能是我犯错的地方。
- 扩大测试图像,保持比例和中心,直到一对边与容器的边重合。
- 对于较窄的显示,左右边缘将首先相遇,顶部和底部将在目标矩形内。
- 但不要现在停下来。那将是适合的比例,或信箱。
- 展开直到顶部和底部与容器的顶部和底部重合。
- 对于较窄的显示器,这意味着两侧的内容都会被裁剪
- 对于13:6显示,所有四个图像边缘将同时与显示边缘重合。
我不知道为什么 .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)