Ios stackview中的布局约束(swift编程)

Ios stackview中的布局约束(swift编程),ios,swift,constraints,Ios,Swift,Constraints,我正在尝试为我的应用程序创建一个关于页面,但我正在努力解决我通过编程方式添加的约束。我还在学习整个概念 这是我的密码,我抄到操场了 import UIKit import PlaygroundSupport class TestViewController: UIViewController { var aboutText:[String] = [] var fbLinks:[String] = [] let scrollView = UIScrollView()

我正在尝试为我的应用程序创建一个关于页面,但我正在努力解决我通过编程方式添加的约束。我还在学习整个概念

这是我的密码,我抄到操场了

import UIKit
import PlaygroundSupport

class TestViewController: UIViewController {

    var aboutText:[String] = []
    var fbLinks:[String] = []

    let scrollView = UIScrollView()
    let stackView = UIStackView()

    override func viewDidLoad() {
        super.viewDidLoad()

        //Add and setup scroll view
        self.view.addSubview(self.scrollView)
        self.scrollView.translatesAutoresizingMaskIntoConstraints = false;


        //Constrain scroll view
        self.scrollView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 5).isActive = true;
        self.scrollView.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 30).isActive = true;
        self.scrollView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: 5).isActive = true;
        self.scrollView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: 0).isActive = true;

        self.scrollView.addSubview(self.stackView)
        self.stackView.translatesAutoresizingMaskIntoConstraints = false
        self.stackView.axis = .vertical
        self.stackView.alignment = UIStackView.Alignment.leading
        self.stackView.spacing = 10;

        //constrain stack view to scroll view
        self.stackView.leadingAnchor.constraint(equalTo: self.scrollView.leadingAnchor).isActive = true;
        self.stackView.topAnchor.constraint(equalTo: self.scrollView.topAnchor).isActive = true;
        self.stackView.trailingAnchor.constraint(equalTo: self.scrollView.trailingAnchor).isActive = true;
        self.stackView.bottomAnchor.constraint(equalTo: self.scrollView.bottomAnchor).isActive = true;

        //constrain width of stack view to width of self.view, NOT scroll view
        self.stackView.widthAnchor.constraint(equalTo: self.view.widthAnchor).isActive = true;

        //Text Label
        aboutText.append("Lorem ipsum dolor sit amet, consectetur adipiscing elit.")
        aboutText.append("Maecenas sed pulvinar est. Integer mattis mollis eleifend. Integer suscipit arcu sit amet erat rhoncus malesuada. Nam feugiat augue id leo maximus dignissim id sed libero. Proin dapibus metus vel nisl ultrices, quis laoreet metus malesuada. Lorem ipsum dolor sit amet, consectetur adipiscing elit. ")
        aboutText.append(" penatibus et magnis dis parturient montes, nascetur ridiculus mus. Sed sit amet dui consectetur, vulputate felis sed, volutpat dui. Quisque eu ex eu nulla facilisis aliquet. Vestibulum vitae lacus non sapien posuere commodo et eget arcu. Sed quis eros condimentum, pharetra ligula non, gravida ex. Cras luctus com")
        aboutText.append(" Praesent luctus nulla eget condimentum volutpat. Nunc metus odio, commodo sit amet placerat non, cursus posuere sem. Mauris lorem felis, elementum vel purus")


        fbLinks.append("Some text")
        fbLinks.append("Some other text but longer")
        fbLinks.append("Some other text but way longer then the previous was")
        fbLinks.append("text again what a surprise")
        fbLinks.append("guess what this is a text too")



        let image = UIImage(systemName: "house")
        let imageView = UIImageView(image: image!)
        imageView.heightAnchor.constraint(equalToConstant: 60).isActive = true
        imageView.widthAnchor.constraint(equalToConstant: 60).isActive = true
        stackView.addArrangedSubview(imageView)

        for text in aboutText
        {
            stackView.addArrangedSubview(generateText(text:text))
        }



        stackView.addArrangedSubview(generateStackedItem(imageName:"bell",text: "contact_us"))
        stackView.addArrangedSubview(generateStackedItem(imageName:"bolt",text: "rate_us_ios"))

        for link in fbLinks
        {
            let sw:UIStackView = generateStackedItem(imageName:"bolt",text: link)
            stackView.addArrangedSubview(sw)
            sw.leadingAnchor.constraint(equalTo: self.stackView.leadingAnchor).isActive = true;
            sw.trailingAnchor.constraint(equalTo: self.stackView.trailingAnchor).isActive = true;
        }



    }

    func generateText(text:String)->UILabel
    {
        let textLabel = UILabel()
        textLabel.widthAnchor.constraint(equalToConstant: self.view.frame.width).isActive = true
        textLabel.text  = NSLocalizedString(text, comment: "")
        textLabel.textAlignment = .left
        textLabel.numberOfLines = 0
        textLabel.lineBreakMode = .byWordWrapping


        return textLabel
    }

    func generateStackedItem(imageName:String,text:String)->UIStackView
    {
        let stackView   = UIStackView()
        stackView.axis  = NSLayoutConstraint.Axis.horizontal
        stackView.distribution  = .fill
        stackView.alignment = UIStackView.Alignment.leading
        stackView.spacing   = 5.0

        let image = UIImage(systemName: imageName)
        let imageView = UIImageView(image: image!)
        imageView.translatesAutoresizingMaskIntoConstraints = false
        imageView.heightAnchor.constraint(equalToConstant: 20).isActive = true
        imageView.widthAnchor.constraint(equalToConstant: 20).isActive = true

        let label = generateText(text: text)

        stackView.addArrangedSubview(imageView)
        stackView.addArrangedSubview(label)

        stackView.translatesAutoresizingMaskIntoConstraints = false

        //stackView.heightAnchor.constraint(equalToConstant: label.frame.height).isActive = true

        stackView.heightAnchor.constraint(equalToConstant: 50).isActive = true



        return stackView
    }

}



let vc = TestViewController()
vc.view.backgroundColor = .white
PlaygroundPage.current.liveView = vc


这就是我在页面上标记了3项内容的方式

  • 我想把大房子的图标放在中间,但我 不知道怎么做,因为我的stackview的对齐方式是前导的

  • 我使链接之间的间距变大,以便可以看到较长的文本,因此我这里的问题是如何设置内部堆栈视图的大小,以取决于包含文本的高度

  • 如何将lightning图标和stackview中的文本垂直居中

  • 我想在stackview内的链接中添加点击手势(带有闪电图标的链接),如果可能的话,我想使用闭包。如果闭包不适用于此,请您帮助我或建议其他解决方案。我试过这样做,但不知怎么的,那对我不起作用


  • 提前谢谢。

    仅供参考,你应该一次只回答一个问题,或者至少只回答相关的问题(换句话说,第4个问题应该是不同的)

    我会把地址从1到3

    首先,您的代码中有一条注释:

    //constrain width of stack view to width of self.view, NOT scroll view
    
    这是错误的。堆栈视图宽度应限制为滚动视图宽度。否则,如果您的滚动视图没有在屏幕上一直延伸,它将水平滚动

    在您的情况下,您(似乎)通过5点的前导和尾随插入滚动视图:

    self.scrollView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 5).isActive = true;
    self.scrollView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: 5).isActive = true;
    
    但是,您的trailingAnchor常量应该是
    -5

    一旦这一点得到纠正

    1)更改“主”堆栈视图的
    。对齐方式也
    。填充
    而不是
    。引导
    ,并确保图像视图具有
    。contentMode=.scalespectfit
    。这将使“房子”水平居中

    2)您可以约束“内部堆栈视图”相对于标签高度的高度。只需确保在将标签添加为arrangedSubview后添加该约束即可

    3)要垂直居中图标->标签,请为水平堆栈视图设置
    .alignment=.center

    以下是您发布的代码的稍微修改版本:

    class TestViewController: UIViewController {
    
        var aboutText:[String] = []
        var fbLinks:[String] = []
    
        let scrollView = UIScrollView()
        let stackView = UIStackView()
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            //Add and setup scroll view
            self.view.addSubview(self.scrollView)
            self.scrollView.translatesAutoresizingMaskIntoConstraints = false;
    
            //Constrain scroll view
            self.scrollView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 5).isActive = true;
            self.scrollView.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 30).isActive = true;
            // trailing constant should be negative
            self.scrollView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: -5).isActive = true;
            self.scrollView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: 0).isActive = true;
    
            self.scrollView.addSubview(self.stackView)
            self.stackView.translatesAutoresizingMaskIntoConstraints = false
            self.stackView.axis = .vertical
            // change to .fill
            self.stackView.alignment = UIStackView.Alignment.leading
            self.stackView.alignment = .fill
            self.stackView.spacing = 10;
    
            //constrain stack view to scroll view
            self.stackView.leadingAnchor.constraint(equalTo: self.scrollView.leadingAnchor).isActive = true;
            self.stackView.topAnchor.constraint(equalTo: self.scrollView.topAnchor).isActive = true;
            self.stackView.trailingAnchor.constraint(equalTo: self.scrollView.trailingAnchor).isActive = true;
            self.stackView.bottomAnchor.constraint(equalTo: self.scrollView.bottomAnchor).isActive = true;
    
            //constrain width of stack view to width of self.view, NOT scroll view
            //self.stackView.widthAnchor.constraint(equalTo: self.view.widthAnchor).isActive = true;
            // you SHOULD constrain the stackView width to the width of the scrollView (assuming you do not want horizontal scrolling)
            self.stackView.widthAnchor.constraint(equalTo: scrollView.widthAnchor).isActive = true;
    
            //Text Label
            aboutText.append("Lorem ipsum dolor sit amet, consectetur adipiscing elit.")
            aboutText.append("Maecenas sed pulvinar est. Integer mattis mollis eleifend. Integer suscipit arcu sit amet erat rhoncus malesuada. Nam feugiat augue id leo maximus dignissim id sed libero. Proin dapibus metus vel nisl ultrices, quis laoreet metus malesuada. Lorem ipsum dolor sit amet, consectetur adipiscing elit. ")
            aboutText.append(" penatibus et magnis dis parturient montes, nascetur ridiculus mus. Sed sit amet dui consectetur, vulputate felis sed, volutpat dui. Quisque eu ex eu nulla facilisis aliquet. Vestibulum vitae lacus non sapien posuere commodo et eget arcu. Sed quis eros condimentum, pharetra ligula non, gravida ex. Cras luctus com")
            aboutText.append(" Praesent luctus nulla eget condimentum volutpat. Nunc metus odio, commodo sit amet placerat non, cursus posuere sem. Mauris lorem felis, elementum vel purus")
    
    
            fbLinks.append("Some text")
            fbLinks.append("Some other text but longer")
            fbLinks.append("Some other text but way longer then the previous was")
            fbLinks.append("text again what a surprise")
            fbLinks.append("guess what this is a text too")
    
    
    
            let image = UIImage(systemName: "house")
            let imageView = UIImageView(image: image!)
            imageView.contentMode = .scaleAspectFit
    
            imageView.heightAnchor.constraint(equalToConstant: 60).isActive = true
    
            stackView.addArrangedSubview(imageView)
    
            for text in aboutText
            {
                stackView.addArrangedSubview(generateText(text:text))
            }
    
            stackView.addArrangedSubview(generateStackedItem(imageName:"bell",text: "contact_us"))
            stackView.addArrangedSubview(generateStackedItem(imageName:"bolt",text: "rate_us_ios"))
    
            for link in fbLinks
            {
                let sw:UIStackView = generateStackedItem(imageName:"bolt",text: link)
                stackView.addArrangedSubview(sw)
                // next two lines are not needed
                //sw.leadingAnchor.constraint(equalTo: self.stackView.leadingAnchor).isActive = true;
                //sw.trailingAnchor.constraint(equalTo: self.stackView.trailingAnchor).isActive = true;
            }
    
        }
    
        func generateText(text:String)->UILabel
        {
            let textLabel = UILabel()
            // no need to set widthAnchor
            //textLabel.widthAnchor.constraint(equalToConstant: self.view.frame.width).isActive = true
            textLabel.text  = NSLocalizedString(text, comment: "")
            textLabel.textAlignment = .left
            textLabel.numberOfLines = 0
            textLabel.lineBreakMode = .byWordWrapping
    
            return textLabel
        }
    
        func generateStackedItem(imageName:String,text:String)->UIStackView
        {
            let stackView   = UIStackView()
            stackView.axis  = NSLayoutConstraint.Axis.horizontal
            stackView.distribution  = .fill
            // horizontal stack view alignment defines the Vertical alignment
            //stackView.alignment = UIStackView.Alignment.leading
            // so set it to .center to get vertical centering
            stackView.alignment = .center
            stackView.spacing   = 5.0
    
            let image = UIImage(systemName: imageName)
            let imageView = UIImageView(image: image!)
            imageView.translatesAutoresizingMaskIntoConstraints = false
            imageView.heightAnchor.constraint(equalToConstant: 20).isActive = true
            imageView.widthAnchor.constraint(equalToConstant: 20).isActive = true
    
            let label = generateText(text: text)
    
            stackView.addArrangedSubview(imageView)
            stackView.addArrangedSubview(label)
    
            stackView.translatesAutoresizingMaskIntoConstraints = false
    
            // constrain stackView height to label height + constant
            //stackView.heightAnchor.constraint(equalToConstant: 50).isActive = true
            stackView.heightAnchor.constraint(equalTo: label.heightAnchor, constant: 16).isActive = true
    
            return stackView
        }
    
    }
    
    结果:


    谢谢@DonMag!你能推荐一个网站、一本书或者一些我能正确学习这些约束知识的东西吗?@J先生-我总是建议从苹果开始:--然后只需搜索(谷歌或任何地方)ios自动布局教程
    。很多链接。。。阅读几十篇教程。到那时,你应该有一个坚实的基础,并且应该能够处理任何发生的事情。