如何以编程方式创建适合内容的居中容器?

时间:2017-11-03 13:52:29

标签: ios swift ios-autolayout

这是在没有使用故事板的情况下以编程方式创建具有未知高度的中心(垂直和水平)容器(应该适应其内部的任何内容)的最佳方法吗?

在下面的示例中,有一个完整大小的背景图像/颜色/等等,并且有一个居中的容器。容器没有固定的高度,如果我想添加或删除控件,它应该适应。控件使用约束在它们之间隔开。

enter image description here

4 个答案:

答案 0 :(得分:1)

如果你的控件如图所示,这是使用UIStackView的完美情况。除了添加视图之外,它还可以扩展,收缩而无需执行任何操作。

然后使用UIStackView上的约束来扩展/收缩包含白色圆角视图。

答案 1 :(得分:0)

在swift 4中你可以这样做:

第一种方式:

    let view = UIView(frame: CGRect(0, 0, 100, 60))
    view.center = self.view.center
    self.view.addSubview(view)

或使用 autoLayout

第二种方式

    let view = UIView()
    view.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
    view.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true
    view.widthAnchor.constraint(equalToConstant: 100).isActive = true
    view.heightAnchor.constraint(equalToConstant: 60).isActive = true

答案 2 :(得分:0)

创建您的containerView。它需要的唯一限制是固定到centerX和centerY:

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

然后,您需要做的只是使用子视图填充它,并确保这些子视图固定到容器视图的所有边缘。然后容器视图可以自我调整大小。

如果您的图片正是您要复制的内容,则甚至不需要第二步:只需使用垂直轴containerView UIStackView,然后添加所有{{1} }}

答案 3 :(得分:0)

第一种方法是使用UIStackView。

第二种方法是以编程方式生成约束。我将对此进行阐述,因为我主要是出于各种原因使用它。

我写了以下扩展名 - 随意使用它:

通过使用它,我可以更轻松地在代码中约束子视图。

我已在项目底部制作了用例样本。

// MARK: Layout priorities which are mostly used
class LayoutPriority {
    static let required: Float = 1000
    static let must: Float = 999
    static let defaultHigh: Float = 750
    static let defaultLow: Float = 250
    static let zero: CGFloat = 0
}


extension UIView {

    // Make sure the view applies to autolayout rules
    private func validateViewForAutolayoutRules() throws -> Bool {
        // Implies it is the caller responsibility to make sure the view has superview
        guard let _ = superview else {
            throw ConstraintErrorType.nullifiedSuperview("Superview is nil");
        }

        // Enable autolayout mechanism
        if translatesAutoresizingMaskIntoConstraints {
            translatesAutoresizingMaskIntoConstraints = false
        }

        return true
    }

    // This method assumes the two views share the same parent
    @discardableResult
    public func layout(_ firstAttribute: NSLayoutAttribute, to secondAttribute: NSLayoutAttribute, of view: UIView, relation: NSLayoutRelation = .equal, multiplier: CGFloat = 1.0, constant: CGFloat = 0, priority: UILayoutPriority = UILayoutPriority.required) -> NSLayoutConstraint? {
        guard let selfValidationSuccess = try? validateViewForAutolayoutRules(), selfValidationSuccess == true else {
            print("\(String(describing: self)) Error in func: \(#function)")
            return nil
        }
        let constraint = NSLayoutConstraint(item: self, attribute: firstAttribute, relatedBy: .equal, toItem: view, attribute: secondAttribute, multiplier: multiplier, constant: constant)
        constraint.priority = priority
        superview!.addConstraint(constraint)
        return constraint
    }

    // Set constant edge
    @discardableResult
    func setConstant(edge: NSLayoutAttribute, value: CGFloat, priority: UILayoutPriority = UILayoutPriority.required) -> NSLayoutConstraint?
    {
        // Enable autolayout mechanism
        translatesAutoresizingMaskIntoConstraints = false

        let constraint = NSLayoutConstraint(item: self, attribute: edge, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1.0, constant: value)
        constraint.priority = priority

        addConstraint(constraint)

        return constraint
    }
}

现在你以这种方式使用它:

  • 您创建containerView,添加它,并将其置于其超级视图中(不设置高度)。
  • 您创建了第一个子视图 - 将其拉伸到containerView的两侧和顶部。
  • 你创建第二个子视图 - 将它拉伸到两侧,它是顶部的 第一个子视图的底部,它位于containerView底部的底部。

那样' containerView'垂直拉伸。

class ViewController: UIViewController {
    func configure() {

        // Generate container
        let containerView = UIView()
        view.addSubview(containerView)

        // Cling center of 'containerView' to it's superview
        containerView.layout(.centerX, to: .centerX, of: view)
        containerView.layout(.centerY, to: .centerY, of: view)
        containerView.layout(.right, to: .right, of: view, constant: -50)
        containerView.layout(.left, to: .left, of: view, constant: 50)

        // Setup first view
        let firstView = UIView()
        containerView.addSubview(firstView)

        // Set constraints on firstView
        firstView.setConstant(edge: .height, value: 50)
        firstView.layout(.left, to: .left, of: containerView, constant: 20)
        firstView.layout(.right, to: .right, of: containerView, constant: -20)
        firstView.layout(.top, to: .top, of: containerView)

        // Setup second view
        let secondView = UIView()
        containerView.addSubview(secondView)

        // Set constraints on second view
        secondView.setConstant(edge: .height, value: 50)
        secondView.layout(.left, to: .left, of: containerView, constant: 20)
        secondView.layout(.right, to: .right, of: containerView, constant: -20)
        secondView.layout(.bottom, to: .bottom, of: containerView, constant: -50)

        // Cling to to the first view
        secondView.layout(.top, to: .bottom, of: firstView, constant: 20)
    }
}