【问题标题】:Can't adjust layouts on multiple devices in Swift无法在 Swift 中调整多个设备上的布局
【发布时间】:2018-10-29 08:16:21
【问题描述】:

我正在尝试在没有 Storyboard 的情况下在 Swift 中调整布局。但是使用下面的代码,我无法在 iPhone Plus 系列(6+、7+ 和 8+)上调整布局。

案例1
使用基于 640x1136 尺寸的图像,它适用于 iPhone8、8+ 和 X。

class Constants {

    // the image parts are based on 640x1136
    static let guiPartsWidthOnDesign = CGFloat(640)
    static var guiPartsMultiplier: CGFloat = UIScreen.main.bounds.width / guiPartsWidthOnDesign

}

制作按钮

for i in 1..<5 {

    let subButton = UIImageView.init(frame: CGRect(
        x: UIScreen.main.bounds.size.width/2-50*Constants.guiPartsMultiplier,
        y: (100*Constants.guiPartsMultiplier)+CGFloat(i*100),
        width: 187*Constants.guiPartsMultiplier,
        height: 100*Constants.guiPartsMultiplier))
    background.addSubview(subButton)
    subButton.backgroundColor = UIColor.blue
    subButton.alpha = 1.0

}

多个设备上的结果看起来布局相同。

案例2
使用基于 750x1334 尺寸的图像,在 iPhone8+ 上效果不佳。

class Constants {

    // the images are based on 750x1334
    static let guiPartsWidthOnDesign = CGFloat(750)
    static var guiPartsMultiplier: CGFloat = UIScreen.main.bounds.width / guiPartsWidthOnDesign

}

制作按钮(与前面的代码相同。)

结果

如您所见,蓝色方块的 y 位置在 iPhone8 和 8 Plus 之间是不同的。 (iPhone8和X的结果是一样的。)

我该如何解决这个问题?

更新
我尝试使用 UIStackView,但效果不佳。

更新2

//Define this as class variable
    fileprivate lazy var stackView: UIStackView = {
        let sv = UIStackView()
        sv.backgroundColor = UIColor.green
        sv.translatesAutoresizingMaskIntoConstraints = false
        sv.axis = .vertical
        sv.alignment = .fill
        sv.distribution = .fillEqually
        sv.spacing = 10
        return sv
    }()

    override func viewDidLoad() {
        super.viewDidLoad()

        self.view.addSubview(stackView)

        stackView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
        stackView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true

        let background = UIImageView.init(frame: UIScreen.main.bounds)
        background.image = UIImage(named:"BG")
        stackView.addSubview(background)
        //        background.translatesAutoresizingMaskIntoConstraints = false
//        background.contentMode = .scaleAspectFill

for i in 1..<5 {

    let subButton = UIImageView()
    subButton.translatesAutoresizingMaskIntoConstraints = false
    subButton.backgroundColor = UIColor.blue
    subButton.alpha = 1.0
    stackView.addArrangedSubview(subButton)
    subButton.widthAnchor.constraint(equalTo: self.view.widthAnchor, multiplier: 0.3).isActive = true

}

}

*对不起,我不知道,但我无法上传截图。

UPDATE3
我使用了以下代码,结果在所有类型的设备上都是这样的:

//Define this as class variable
    fileprivate lazy var stackView: UIStackView = {
        let sv = UIStackView()
        sv.translatesAutoresizingMaskIntoConstraints = false
        sv.axis = .vertical
        sv.alignment = .fill
        sv.distribution = .fillEqually
        sv.spacing = 10
        return sv
    }()

    fileprivate lazy var catBg: UIImageView = {
        let iv = UIImageView()
        iv.translatesAutoresizingMaskIntoConstraints = false
        iv.contentMode = .scaleAspectFill
        iv.image = UIImage(named: "BG")
        return iv
    }()


    override func viewDidLoad() {
        super.viewDidLoad()

        self.view.addSubview(catBg)
        catBg.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
        catBg.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true
        catBg.widthAnchor.constraint(equalTo: self.view.widthAnchor, multiplier: 0.7).isActive = true
        catBg.heightAnchor.constraint(equalTo: catBg.widthAnchor, multiplier: 1.78).isActive = true

        self.catBg.addSubview(stackView)
        stackView.centerXAnchor.constraint(equalTo: catBg.centerXAnchor).isActive = true
        stackView.centerYAnchor.constraint(equalTo: catBg.centerYAnchor).isActive = true


        for i in 1..<5 {

            let subButton = UIImageView()
            subButton.translatesAutoresizingMaskIntoConstraints = false
            subButton.backgroundColor = UIColor.blue
            subButton.alpha = 1.0
            stackView.addArrangedSubview(subButton)
            subButton.widthAnchor.constraint(equalTo: catBg.widthAnchor, multiplier: 0.3).isActive = true
            //If you have an image you can remove or change this anchor
            subButton.heightAnchor.constraint(equalToConstant: 54).isActive = true
        }

    }

UPDATE4

我的理想是这张图片的中心。但到目前为止,结果就像正确的图像。

【问题讨论】:

  • 因为您使用的是 UIScreen.main.bounds.width,它会随着您使用的设备类型而变化,除以一个常数。当然,不同的设备会得到不同的结果?
  • @progammingBeignner 是的,你是对的。但是,如果我使用基于 640x1136 图像的图像并使用 case1 代码。但是当我尝试案例 2 时,只更改了基本图像大小和图像大小的数量,它确实运行良好。所以我想问你为什么如果在 750x1334 上它不起作用...

标签: ios swift xcode


【解决方案1】:

即使您不使用情节提要,我也建议您使用UIStackview。在堆栈视图中,您可以根据需要将特定轴垂直和间距。将 stackview 设置为平均填充。

不要使用实际帧来计算多个屏幕布局的位置,这会变得乏味。 您应该在特定锚点中使用自动布局约束。

//Define this as class variable
fileprivate lazy var stackView: UIStackView = {
    let sv = UIStackView()
    sv.translatesAutoresizingMaskIntoConstraints = false
    sv.axis = .vertical
    sv.alignment = .fill
    sv.distribution = .fillEqually
    sv.spacing = 10
    return sv
}()

fileprivate lazy var catBg: UIImageView = {
    let iv = UIImageView()
    iv.translatesAutoresizingMaskIntoConstraints = false
    iv.contentMode = .scaleAspectFill
    iv.image = UIImage(named: "your_img_name")
    return iv
}()

//Put this in viewDidLoad
//Edit

self.view.addSubview(catBg)
//catBg.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
//catBg.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true
//catBg.widthAnchor.constraint(equalTo: self.view.widthAnchor, multiplier: 0.7).isActive = true
//catBg.heightAnchor.constraint(equalTo: catBg.widthAnchor, multiplier: 1.78).isActive = true

catBg.topAnchor.constraint(equalTo: self.view.topAnchor).isActive = true
catBg.leftAnchor.constraint(equalTo: self.view.leftAnchor).isActive = true
catBg.rightAnchor.constraint(equalTo: self.view.rightAnchor).isActive = true
catBg.bottomAnchor.constraint(equalTo: self.view.bottomAnchor).isActive = true

self.catBg.addSubview(stackView)
stackView.centerXAnchor.constraint(equalTo: catBg.centerXAnchor).isActive = true
stackView.centerYAnchor.constraint(equalTo: catBg.centerYAnchor).isActive = true

for i in 1..<5 {

    let subButton = UIImageView()
    subButton.translatesAutoResizingMaskIntoConstraints = false
    subButton.backgroundColor = UIColor.blue
    subButton.alpha = 1.0
    stackView.addArrangedSubview(subButton)
    subButton.widthAnchor.constraint(equalTo: catBg.widthAnchor, multiplier: 0.3).isActive = true
    //If you have an image you can remove or change this anchor
    subButton.heightAnchor.constraint(equalToConstant: 54).isActive = true
}

【讨论】:

  • 我尝试使用stackView,但效果不佳(我在问题中添加了结果屏幕)。那么我只有一种使用自动布局锚点的解决方案吗?不能用位置计算调整布局吗?
  • 使用stackView,您的间距已经更加一致。圆形粉色框是 UIView 吗?
  • 圆形粉红色框包含在背景视图中。蓝色框是 UIView,其他对象不是。
  • 你在stackView中添加了什么约束?
  • 没什么,只是写了你在回答中提到的代码。
猜你喜欢
  • 2020-10-02
  • 2017-07-18
  • 1970-01-01
  • 1970-01-01
  • 2015-06-13
  • 1970-01-01
  • 2015-04-15
  • 1970-01-01
  • 2015-03-27
相关资源
最近更新 更多