Stackview内的布局约束(以编程方式快速移动)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Stackview内的布局约束(以编程方式快速移动)相关的知识,希望对你有一定的参考价值。
我正在尝试为我的应用程序创建一个About页面,但我在以编程方式添加的约束中苦苦挣扎。我仍在学习整个概念。
这是我的代码,我已复制到操场上
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的对齐方式是领先的。
我将链接之间的间距增大,以便可以看到我的较长文本,所以我的问题是如何根据所包含文本的高度来设置内部stackview的大小。
如何将闪电图标和文本垂直放置在stackview中?
我想向我的stackview中的链接(带有闪电图标的链接)添加敲击手势,如果可能的话,我希望使用闭包操作。如果不能使用闭包,可以请我帮忙,或者建议其他解决方案。我这样尝试过,但对我不起作用link
先谢谢您。
FYI,您应该一次只回答一个问题-或至少只回答[[相关个问题(换句话说,#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常数应为也将“主” stackView的-5
。一旦更正...
[[[1]
.alignment
更改为.fill
,而不是.leading
,并确保图像视图具有.contentMode = .scaleAspectFit
。这将使“房屋”水平居中。[[2)
可以相对于标签的高度限制“内部堆栈视图”的高度。只需确保添加该约束after将标签添加为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
}
}
结果:
以上是关于Stackview内的布局约束(以编程方式快速移动)的主要内容,如果未能解决你的问题,请参考以下文章
StackView 中的按钮约束(以 Swift 编程方式)
如何以编程方式快速向 UITableViewCell 内的 UIStackView 添加约束?
Swift - StackView 和添加约束,以编程方式添加视图到堆栈 - 加载后调整单元格高度?