仅使用约束(IOS)初始化自定义UIView

时间:2016-12-10 21:23:23

标签: ios swift cocoa-touch uiview nslayoutconstraint

我被指示制作一个井字游戏。

要求是:

  1. 仅使用MVC
  2. 以编程方式显示视图
  3. 仅使用约束设置方块的大小
  4. 因此,我创建了一个Board类和一个Square类。董事会类它几乎只是一个背景颜色的UIView。我在初始化中的主要问题。每次我使用Custom UIView时,我都必须使用CGRect框架初始化。教师告诉我们不要直接使用CGRect函数设置视图的帧,而只是使用约束。

    这就是问题所在。我试图在另一个视图内初始化一个板。因为该板是UIView的子类,所以我 HAVE 来设置一个帧。

    如何在没有框架的情况下初始化UIView,这样你只能使用传入的参数来设置UIView的约束来设置它的大小?

    以下是我现在正在做的事情。我想在没有frame参数的情况下初始化它,但它是必需的。我想初始化这个类,并在另一个viewcontroller类的viewDidLoad函数中使用它。我想传递UIView作为参数,并根据特定视图调整约束。

    class Board: UIView {
    init(frame: CGRect, view: UIView) {
        super.init(frame: frame)
        self.backgroundColor = .green
        self.translatesAutoresizingMaskIntoConstraints = false
        addConstraints(view: view)
    }
    
    func addConstraints(view:UIView){
        NSLayoutConstraint(item: view,
                           attribute: .leading,
                           relatedBy: .equal,
                           toItem: view,
                           attribute: .leading,
                           multiplier: 1,
                           constant: 0).isActive = true
        NSLayoutConstraint(item: view,
                           attribute: .trailing,
                           relatedBy: .equal,
                           toItem: view,
                           attribute: .trailing,
                           multiplier: 1,
                           constant: 0).isActive = true
    
        NSLayoutConstraint(item: view,
                           attribute: .height,
                           relatedBy: .equal,
                           toItem: view,
                           attribute: .height,
                           multiplier: 1,
                           constant: 0).isActive = true
        NSLayoutConstraint(item: view,
                           attribute: .width,
                           relatedBy: .equal,
                           toItem: view,
                           attribute: .width,
                           multiplier: 1,
                           constant: 0).isActive = true
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    

    当我创建board类时,我想在初始化类时将约束设置为我作为参数传入的view。令人沮丧的是,它不会生效,因为我必须使用所需的帧初始化器。

    有什么方法吗?

3 个答案:

答案 0 :(得分:1)

您可以使用默认框架进行初始化。应用约束时,约束将覆盖您设置的原始帧。

class CustomView: UIView {
    init(frame: CGRect, otherParam: Int) {
        super.init(frame: frame) // Init with in case there are no constraints

        setup()
    }
}

class CustomView: UIView {
    init(otherParam: Int) {
        let frame = CGRect(x: 0, y:0, width: 100, height: 100)
        super.init(frame: frame) // Init with a default frame

        setup()
    }
}

答案 1 :(得分:0)

你可以简单地做到这一点。这是代码

    //create
    let childredView = UIView()
    childredView.translatesAutoresizingMaskIntoConstraints = false
    childredView.backgroundColor = UIColor.purple

    //add it
    self.view.addSubview(childredView)
    self.view.bringSubview(toFront: childredView)

    //set constraints
    let views = ["childrenView": childredView]
    let vertical = NSLayoutConstraint.constraints(withVisualFormat: "V:|[childrenView]|", options: [], metrics: nil, views: views)
    let horizontal = NSLayoutConstraint.constraints(withVisualFormat: "H:|[childrenView]|", options: [], metrics: nil, views: views)
    let all = vertical + horizontal

    //activate them
    NSLayoutConstraint.activate(all)

顺便说一句,你不需要框架,因为这个值是计算出来的。您可以创建视图,添加视图并设置适当的约束。希望这可以帮到你。

答案 2 :(得分:0)

你的约束是错误的;你试图限制自己的观点。您是否试图限制视图以填充其超级视图?

    extension UIView {
        func constrainToSuperView() {
            translatesAutoresizingMaskIntoConstraints = false
            let attributes: [NSLayoutAttribute] = [.top, .bottom, .leading, .trailing]
            attributes.forEach { NSLayoutConstraint(item: self, attribute: $0, relatedBy: .equal, toItem: self.superview, attribute: $0, multiplier: 1, constant: 0).isActive = true}
        }
    }

同样,NSLayoutAnchor比NSLayoutConstraint更加初学者友好,因为它的强类型:

    extension UIView {
        func constrainToSuperView() {
            guard let superview = superview else {
                return
            }
            translatesAutoresizingMaskIntoConstraints = false
            topAnchor.constraint(equalTo: superview.topAnchor).isActive = true
            bottomAnchor.constraint(equalTo: superview.bottomAnchor).isActive = true
            leadingAnchor.constraint(equalTo: superview.leadingAnchor).isActive = true
            trailingAnchor.constraint(equalTo: superview.trailingAnchor).isActive = true
        }
    }