如何在 SwiftUI 中以相同的尺寸显示不同屏幕尺寸的屏幕?

How can I show in SwiftUI a screen in different screen sizes with the same measures?

我的应用在不同屏幕尺寸下出现问题。我举了一个小例子来说明问题。 我有一个屏幕,左边是文本和按钮,右边是图像。在这之后,在 zstack 中,我有相同的图像更大,并且在该图像上有一层不透明度 0.5。

问题是我使用的是相对于屏幕的测量结果不同。在所附的图片中,您可以看到差异。

这是代码。

struct Screen2: View {
var body: some View {
    VStack {
        ZStack {
            ZStack {
                Image(uiImage: resizeImage(image: UIImage.init(named: "cover.jpeg")!, targetSize: .init(width: UIScreen.main.bounds.size.width, height: UIScreen.main.bounds.size.width)))
                    .resizable()
                    .aspectRatio(contentMode: .fill)
                    .frame(width: UIScreen.main.bounds.size.width, height: UIScreen.main.bounds.size.height / 2.9, alignment: .center)
                    .cornerRadius(0)
                Color.black
                    .frame(width: UIScreen.main.bounds.size.width, height: UIScreen.main.bounds.size.height / 2.9, alignment: .center)
                    .opacity(0.5)
            }
            .edgesIgnoringSafeArea(.all)
            .frame(width: UIScreen.main.bounds.size.width, height: UIScreen.main.bounds.size.height / 5, alignment: .top)
            HStack(alignment: .top) {
                VStack {
                    Text("The Suicide Squad")
                        .font(.title)
                        .shadow(color: .white, radius: 5)
                    Button("Publish") {
                        print("Published")
                    }
                    .background(Color.blue)
                    .foregroundColor(.white)
                    .padding()
                }
                .padding([.leading], 10)
                Spacer()
                Image(uiImage: resizeImage(image: UIImage.init(named: "cover.jpeg")!, targetSize: CGSize.init(width: UIScreen.main.bounds.width / 4, height: UIScreen.main.bounds.height / 4)))
            }
        }
        HStack {
            Spacer()
            Text("TESTING")
            Spacer()
        }
        .background(Color.red)
        Spacer()
    }
}

func resizeImage(image: UIImage, targetSize: CGSize) -> UIImage {
    let size = image.size
    let widthRatio = targetSize.width / size.width
    let heightRatio = targetSize.height / size.height
    var newSize:CGSize
    if (widthRatio > heightRatio)
    {
        newSize = CGSize(width: size.width * heightRatio, height: size.height * heightRatio)
    }
    else
    {
        newSize = CGSize(width: size.width * widthRatio, height: size.height * widthRatio)
    }
    let rect = CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height)
    UIGraphicsBeginImageContextWithOptions(newSize, false, 1.0)
    image.draw(in: rect)
    let newImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    return newImage!
}

}

任何人都可以帮助我在每个屏幕尺寸下以相同的方式显示结果吗?

谢谢

  1. 您正在将封面大小调整为一个 targetSize,然后使用 .frame 设置另一个大小,然后再向容器 ZStack 添加一个框架。你为什么要那样做?
  2. 当更改图像框架并将 contentMode 设置为 .fill 时,它将在其框架中居中,但图像的其余部分将在框架外可见。你可以在这个例子中看到:
let targetSize = CGSize(width: UIScreen.main.bounds.size.width, height: UIScreen.main.bounds.size.height / 2.9)

Image("cover")
    .resizable()
    .aspectRatio(contentMode: .fill)
    .cornerRadius(0)
    .frame(width: targetSize.width, height: targetSize.height, alignment: .center)
    .overlay(Rectangle().stroke(lineWidth: 5).foregroundColor(.red))

这可以用 .clipped() 修饰符修复。如果您熟悉

,它与 UIKit 上的 clipsToBounds 相同
  1. 当您将 edgesIgnoringSafeArea 应用于 VStack 中的一个项目时,它的工作方式类似于 offset 修饰符,这意味着下一个项目不会紧随其后。您需要将 edgesIgnoringSafeArea 应用于整个 VStack,并且如果需要,您可以禁用 if .edgesIgnoringSafeArea([]) 用于需要安全区域插入
  2. 的项目
  3. 在将图像传递给 Image 之前无需调整图像大小,尤其是您不想在视图生成器函数中执行此操作,因为每次更新此视图时都会重新计算。通常应用所需的修饰符完全足以获得所需的结果,让 SwiftUI 为您优化它:
VStack(spacing: 0) {
    ZStack(alignment: .bottom) {
        let targetSize = CGSize(width: UIScreen.main.bounds.size.width, height: UIScreen.main.bounds.size.height / 2.9)

        ZStack {
            Image("cover")
                .resizable()
                .aspectRatio(contentMode: .fill)
                .cornerRadius(0)
                .frame(width: targetSize.width, height: targetSize.height, alignment: .center)
                .clipped()
            Color.black
                .opacity(0.5)
        }
        .frame(width: targetSize.width, height: targetSize.height, alignment: .center)
        HStack(alignment: .top) {
            VStack {
                Text("The Suicide Squad")
                    .font(.title)
                    .shadow(color: .white, radius: 5)
                Button("Publish") {
                    print("Published")
                }
                .background(Color.blue)
                .foregroundColor(.white)
                .padding()
            }
            .padding([.leading], 10)
            Spacer()
            Image("cover")
                .resizable()
                .aspectRatio(contentMode: .fit)
                .frame(width: UIScreen.main.bounds.width / 4)
        }
        .edgesIgnoringSafeArea([])
    }
    HStack {
        Spacer()
        Text("TESTING")
        Spacer()
    }
    .background(Color.red)
    Spacer()
}
.edgesIgnoringSafeArea(.all)

结果: