ios - 堆栈视图内的布局约束(以编程方式快速)
问题描述
我正在尝试为我的应用程序创建一个关于页面,但我正在努力解决我以编程方式添加的约束。我还在学习整个概念。
这是我的代码,我复制到操场上
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中的链接(带有闪电图标的链接)中添加点击手势,如果可能的话,我想用闭包来做到这一点。如果关闭不是为此,您能否帮助我或建议其他解决方案。我像这样尝试过,但这对我不起作用链接
先感谢您。
解决方案
仅供参考,您应该尝试一次只解决一个问题 - 或者至少只解决相关问题(换句话说,#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)更改您的“主要”stackView.alignment
而.fill
不是.leading
,并确保您的图像视图具有.contentMode = .scaleAspectFit
. 这将使“房子”水平居中。
2)您可以限制“内部堆栈视图”相对于标签高度的高度。只需确保将标签添加为排列子视图后添加该约束
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
}
}
结果:
推荐阅读
- mongodb - MongoDB 根据条件返回不同的值
- weka - 我不明白参数 C 和 M 如何在 Weka 上工作,尤其是在决策树上
- macos - AppKit 上的 SwiftUI - 在弹出窗口中将焦点设置为 TextField
- html - 如何保持文本静态
- text - 选项卡的语法颜色;回线;正文 (VIM, .txt)
- highcharts - Highcharts 组织结构图:悬挂布局中的重叠子项
- jdbc - 是否可以通过使用带有 jdbctemplate 的实体来插入
- javascript - 打字稿:如何设置清除分数的按钮?
- javascript - RangeError [ERR_HTTP_INVALID_STATUS_CODE]:无效状态代码:4
- javascript - 试图从消息中获取 channelId