需要根据我的设备大小

时间:2018-02-11 17:42:22

标签: ios autolayout uistackview

我在代码中构建我的屏幕,其中包含一个包含我的文本字段的stackView。这个stackView在iPhone 8 / 8Plus / X设备上看起来很棒,但在SE屏幕上却太大了。我意识到我需要按照设备大小按比例调整stackView的大小,但我不确定如何以编程方式。我见过的所有教程都展示了如何在IB中完成。

以下是我正在使用的代码:

        let textFieldStackView = UIStackView(arrangedSubviews: [nameTextField, emailTextField, passwordTextField])
        textFieldStackView.translatesAutoresizingMaskIntoConstraints = false
        textFieldStackView.distribution = .fillEqually
        textFieldStackView.axis = .vertical
        textFieldStackView.spacing = 10

        view.addSubview(textFieldStackView)

        textFieldStackView.topAnchor.constraint(equalTo: logoImageView.bottomAnchor, constant: 100).isActive = true
        textFieldStackView.heightAnchor.constraint(equalToConstant: 150).isActive = true
        textFieldStackView.widthAnchor.constraint(equalToConstant: 350).isActive = true
        textFieldStackView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true

这不仅仅是宽度,而是我需要相应增长的高度。我将如何在代码中执行此操作?

4 个答案:

答案 0 :(得分:1)

如果您需要将视图剪切到屏幕的边缘,则应使用safeArea作为顶部/底部约束以及前导和尾随约束的前导和尾部边距。这样,您的视图在您需要的任何设备上都会很棒 EG:

yourView.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor).isActive = true
yourView.bottomAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor).isActive = true
yourView.leadingAnchor.constraint(equalTo: self.view.layoutMarginsGuide.leadingAnchor).isActive = true
yourView.trailingAnchor.constraint(equalTo: self.view.layoutMarginsGuide.trailingAnchor).isActive = true

它是ios 11代码。为支持iOS 10布局,使用控件的顶部和底部锚点使用self.topLayoutGuide.bottomAnchor和self.bottomLayoutGuide.topAnchor。
在autolayout中使用autolayout非常正确,而不是在顶部评论中使用UISCreenSizes。 https://useyourloaf.com/blog/safe-area-layout-guide/学习本指南,它有点帮助。

编辑:
如果你想让你的视图在中心并根据屏幕大小改变它的大小,同时具有相等的间距前导和尾随我看到的最好的方法是在你的视图的左侧和右侧使用支持视图,这将具有相同的宽度。在中心(您的)视图上调整压缩阻力,您将使其变得更宽 这样的事情:
Example

EDIT2:
根据您的评论和代码:

yourView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
yourView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true
yourView.leadingAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.leadingAnchor, constant: 10).isActive = true
yourView.trailingAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.trailingAnchor, constant: 10).isActive = true
yourView.bottomAnchor.constraintGreaterThanOrEqualToSystemSpacingBelow(self.view.safeAreaLayoutGuide.bottomAnchor, multiplier: 1.0).isActive = true
yourView.topAnchor.constraintGreaterThanOrEqualToSystemSpacingBelow(self.view.safeAreaLayoutGuide.topAnchor, multiplier: 1.0).isActive = true
yourView.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
yourView.setContentCompressionResistancePriority(.defaultLow, for: .vertical)

答案 1 :(得分:1)

您可以将值从一个设备屏幕(下例中的6S)缩放到另一个..

func ScaleWidth(CGFloat value) -> CGFloat {
    return round(value * (UIScreen.main.bounds.size.width / CGFloat(375.0)));
}

func ScaleHeight(CGFloat value) -> CGFloat {
    return round(value * (UIScreen.main.bounds.size.height / CGFloat(667.0)));
}



textFieldStackView.topAnchor.constraint(equalTo: logoImageView.bottomAnchor, constant: ScaleHeight(100.0)).isActive = true
textFieldStackView.heightAnchor.constraint(equalToConstant: ScaleHeight(150.0)).isActive = true
textFieldStackView.widthAnchor.constraint(equalToConstant: ScaleWidth(350.0)).isActive = true
textFieldStackView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true

另一种选择是使用约束乘数:

func AspectWidth() -> CGFloat {
    return round(UIScreen.main.bounds.size.width / CGFloat(375.0));
}

func AspectHeight() -> CGFloat {
    return round(UIScreen.main.bounds.size.height / CGFloat(667.0));
}



textFieldStackView.topAnchor.constraint(equalTo: logoImageView.bottomAnchor, constant: 100.0, multiplier: AspectHeight()).isActive = true
textFieldStackView.heightAnchor.constraint(equalToConstant: 150.0, multiplier: AspectHeight()).isActive = true
textFieldStackView.widthAnchor.constraint(equalToConstant: 350.0, multiplier: AspectWidth()).isActive = true
textFieldStackView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true

答案 2 :(得分:0)

最简单的解决方案(但不是最漂亮的解决方案)是使用UIScreen.main.frame来计算约束的常量。 UIScreen.main.frame表示整个屏幕的帧,每个设备上都有所不同(iPhone SE上为320x568,iPhone 8上为375x667)。

如果您希望堆栈视图在每台设备上看起来相同,那么您的代码可能如下所示:

    let textFieldStackView = UIStackView(arrangedSubviews: [nameTextField, emailTextField, passwordTextField])
    textFieldStackView.translatesAutoresizingMaskIntoConstraints = false
    textFieldStackView.distribution = .fillEqually
    textFieldStackView.axis = .vertical
    textFieldStackView.spacing = UIScreen.main.frame.height / 66.7 // will be 10 on iPhone 8

    view.addSubview(textFieldStackView)

    textFieldStackView.topAnchor.constraint(equalTo: logoImageView.bottomAnchor, constant: UIScreen.main.frame.height / 6.67).isActive = true
    textFieldStackView.heightAnchor.constraint(equalToConstant: UIScreen.main.frame.height / 4.45).isActive = true
    textFieldStackView.widthAnchor.constraint(equalToConstant: UIScreen.main.frame.width / 1.07).isActive = true
    textFieldStackView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true

答案 3 :(得分:0)

我不能评论kiwisip的答案,所以我必须在这里写一下 - 使用UIScreen.main.frame不是一个好的解决方案,最好依靠视图的大小,你可以在其中添加你的堆栈查看为子视图。在您的示例中,您必须使用以下内容替换widthAnchor约束:

textFieldStackView.widthAnchor.constraint(equalTo: view.widthAnchor, constant: 0).isActive = true

另一方面 - 使用超常视图大小除以常量而不是仅使用常量值可能是一个好主意,但这取决于您的布局。