【问题标题】:AutoLayout constraints for programmatically added buttons in a scrollView在 scrollView 中以编程方式添加按钮的 AutoLayout 约束
【发布时间】:2015-11-21 22:55:02
【问题描述】:

我正在努力使自动布局适用于填充了未知数量按钮的水平滚动视图(在这种情况下,数字存储在 sceneCount 中)。 我也尝试过以其他方式解决问题,但这似乎是我能得到的最接近结果(没有矛盾的约束)。不幸的是,我在运行时只得到一个白屏,没有错误。 This 是我希望我的 scrollView 的样子。 希望大家能发现问题!

import UIKit

class ViewController: UIViewController {

let sceneCount = 4
var button = UIButton.buttonWithType(UIButtonType.System) as! UIButton
var buttons: [UIButton] = [UIButton]()


func makeLayout(){

    //Make the content view
    let view1 = UIScrollView()
    view1.setTranslatesAutoresizingMaskIntoConstraints(false)
    view1.backgroundColor = UIColor.redColor()

    //Make the scroll view
    let view2 = UIScrollView()
    view2.setTranslatesAutoresizingMaskIntoConstraints(false)
    view2.backgroundColor = UIColor(red: 0.75, green: 0.75, blue: 0.1, alpha: 1.0)

    view.addSubview(view1)
    view2.addSubview(view1)

    //Create the buttons
    for i in 0...(sceneCount-1) {
        button.setTranslatesAutoresizingMaskIntoConstraints(false)
        button.addTarget(self, action: Selector("scene\(i)Pressed"), forControlEvents: UIControlEvents.TouchUpInside)
        button.setBackgroundImage(UIImage(named: "Scene\(i+1)"), forState: UIControlState.Normal)
        button.sizeThatFits(CGSizeMake(40, 40))

        buttons.append(button)
        view1.addSubview(button)

    }

    //set horizontal spacing between the buttons
    for i in 1...(sceneCount-2) {
        var button1 = UIButton.buttonWithType(UIButtonType.System) as! UIButton
        var button2 = UIButton.buttonWithType(UIButtonType.System) as! UIButton
        button1 = buttons[i - 1]
        button2 = buttons[i]
        var dictionary1 = [String: UIButton]()
        dictionary1.updateValue(button1, forKey: "scene1")
        dictionary1.updateValue(button2, forKey: "scene2")

        view1.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:[scene1]-[scene2]", options: NSLayoutFormatOptions(0), metrics: nil, views: dictionary1) as [AnyObject])
    }

    //set vertical spacing for all buttons
    for i in 0...(sceneCount-1) {
        var button1 = UIButton.buttonWithType(UIButtonType.System) as! UIButton
        button1 = buttons[i]
        var dictionary2 = [String: UIButton]()
        dictionary2.updateValue(button1, forKey: "button1")

        view1.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-0-[button1]-0-|", options: NSLayoutFormatOptions(0), metrics: nil, views: dictionary2) as [AnyObject])
    }

    //set horizontal distance to container for first button
    if sceneCount > 0 {
        var buttonFirst: UIButton = buttons[0]
        var dictionary3 = [String: UIButton]()
        dictionary3.updateValue(buttonFirst, forKey: "buttonFirst")
        view1.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-0-[buttonFirst]", options: NSLayoutFormatOptions(0), metrics: nil, views: dictionary3) as [AnyObject])
    }

    //set horizontal distance to container for last button
    if sceneCount > 0 {
        var buttonLast: UIButton = buttons[sceneCount-1]
        var dictionary4 = [String: UIButton]()
        dictionary4.updateValue(buttonLast, forKey: "buttonLast")
        view1.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:[buttonLast]-0-|", options: NSLayoutFormatOptions(0), metrics: nil, views: dictionary4) as [AnyObject])
    }

}

override func viewDidLoad() {
    super.viewDidLoad()
    makeLayout()
}


override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
}

}

【问题讨论】:

    标签: ios swift uiscrollview autolayout


    【解决方案1】:

    我设法通过以下三个主要更改使您的代码工作:

    1 - 你的内容视图需要是 UIView 类型

    let view1 = UIView()
    

    此视图将包含一个 UIScrollView (view2),并且必须设置它们的约束。在 view1 上,您将能够设置滚动视图的大小,这就是为什么我将视图 2 与超级视图的距离设为 0。

    view1.addSubview(view2)
    
    var dictionary = [String: UIView]()
    dictionary.updateValue(view1, forKey: "view1")
    view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-0-[view1]-0-|", options: NSLayoutFormatOptions(0), metrics: nil, views: dictionary) as [AnyObject])
    view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-0-[view1]-0-|", options: NSLayoutFormatOptions(0), metrics: nil, views: dictionary) as [AnyObject])
    
    dictionary = [String: UIView]()
    dictionary.updateValue(view2, forKey: "view2")
    view1.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-0-[view2]-0-|", options: NSLayoutFormatOptions(0), metrics: nil, views: dictionary) as [AnyObject])
    view1.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-0-[view2]-0-|", options: NSLayoutFormatOptions(0), metrics: nil, views: dictionary) as [AnyObject])
    

    2 - 当您使用相同的引用来创建新按钮时,最终数组的每个位置都会有相同的按钮。 我在创建按钮的 for 中移动了每个按钮的初始化。

    var button = UIButton.buttonWithType(UIButtonType.System) as! UIButton
    view2.addSubview(button)
    

    3- 之后,我刚刚更新了要在按钮和滚动视图 (view2) 之间插入的约束。

    这是最终代码:

    import UIKit
    
    class ViewController: UIViewController {
    
    let sceneCount = 4
    var buttons: [UIButton] = [UIButton]()
    
    func makeLayout(){
    
        //Make the content view
        let view1 = UIView()
        view1.setTranslatesAutoresizingMaskIntoConstraints(false)
        view1.backgroundColor = UIColor.redColor()
    
        //Make the scroll view
        let view2 = UIScrollView()
        view2.setTranslatesAutoresizingMaskIntoConstraints(false)
        view2.backgroundColor = UIColor(red: 0.75, green: 0.75, blue: 0.1, alpha: 1.0)
    
        view.addSubview(view1)
        view1.addSubview(view2)
    
        var dictionary = [String: UIView]()
        dictionary.updateValue(view1, forKey: "view1")
    
        view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-0-[view1]-0-|", options: NSLayoutFormatOptions(0), metrics: nil, views: dictionary) as [AnyObject])
        view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-0-[view1]-0-|", options: NSLayoutFormatOptions(0), metrics: nil, views: dictionary) as [AnyObject])
    
        dictionary = [String: UIView]()
        dictionary.updateValue(view2, forKey: "view2")
    
        view1.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-0-[view2]-0-|", options: NSLayoutFormatOptions(0), metrics: nil, views: dictionary) as [AnyObject])
        view1.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-0-[view2]-0-|", options: NSLayoutFormatOptions(0), metrics: nil, views: dictionary) as [AnyObject])
    
        //Create the buttons
        for i in 0...(sceneCount-1) {
            var button = UIButton.buttonWithType(UIButtonType.System) as! UIButton
    
            button.setTranslatesAutoresizingMaskIntoConstraints(false)
            button.addTarget(self, action: Selector("scene\(i)Pressed"), forControlEvents: UIControlEvents.TouchUpInside)
            button.setBackgroundImage(UIImage(named: "Scene\(i+1)"), forState: UIControlState.Normal)
            button.sizeThatFits(CGSizeMake(40, 40))
    
            buttons.append(button)
            view2.addSubview(button)
        }
    
        //set vertical spacing for all buttons
        for i in 0...(sceneCount-1) {
            var button1 = buttons[i]
            var dictionary2 = [String: UIButton]()
            dictionary2.updateValue(button1, forKey: "button1")
    
            view2.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-0-[button1]-0-|", options: NSLayoutFormatOptions(0), metrics: nil, views: dictionary2) as [AnyObject])
        }
    
        //set horizontal distance to container for first button
        if sceneCount > 0 {
            var buttonFirst: UIButton = buttons[0]
            var dictionary3 = [String: UIButton]()
            dictionary3.updateValue(buttonFirst, forKey: "buttonFirst")
            view2.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-[buttonFirst]", options: NSLayoutFormatOptions(0), metrics: nil, views: dictionary3) as [AnyObject])
        }
    
        //set horizontal spacing between the buttons
        for i in 1...(sceneCount-1) {
            var button1 = buttons[i - 1]
            var button2 = buttons[i]
    
            var dictionary1 = [String: UIButton]()
            dictionary1.updateValue(button1, forKey: "scene1")
            dictionary1.updateValue(button2, forKey: "scene2")
    
            view2.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:[scene1]-[scene2]", options: NSLayoutFormatOptions(0), metrics: nil, views: dictionary1) as [AnyObject])
        }
    
        //set horizontal distance to container for last button
        if sceneCount > 0 {
            var buttonLast: UIButton = buttons[sceneCount-1]
            var dictionary4 = [String: UIButton]()
            dictionary4.updateValue(buttonLast, forKey: "buttonLast")
            view2.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:[buttonLast]-|", options: NSLayoutFormatOptions(0), metrics: nil, views: dictionary4) as [AnyObject])
        }
    
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        makeLayout()
    }
    
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
    }
    

    【讨论】:

    • 完美运行!不知道为什么我将 view1 声明为滚动视图。其他指南指出 UIView 应该在 UIScrollView 内而不是相反,但我想这不是它应该如何工作的。
    • 很高兴知道!为了将来参考,每当我遇到滚动视图问题时,我都会阅读这篇文章:stackoverflow.com/questions/20223021/…
    猜你喜欢
    • 2021-08-09
    • 2014-01-05
    • 2021-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多