无法以编程方式在 Swift 的堆栈视图中正确排列两个标签
Posted
技术标签:
【中文标题】无法以编程方式在 Swift 的堆栈视图中正确排列两个标签【英文标题】:Unable to properly arrange two UILabels in a Stackview in Swift programatically 【发布时间】:2018-06-22 06:15:35 【问题描述】:这是我的层次结构:
-
将包含行的垂直 Stackview (mystack)
视图、包装器(父视图)
将包含两个标签的水平 Stackview (stacktmp)
标签 x2 (tx, tx2)
另外:mystack 有 4 个约束:前导、尾随、顶部和底部与“安全视图”相同。
代码:
let parentview = UIView()
parentview.backgroundColor = UIColor.cyan
let stacktmp = UIStackView()
stacktmp.axis = .horizontal
let tx = UILabel()
tx.text = "ss"
tx.backgroundColor = UIColor.red
tx.font = UIFont.boldSystemFont(ofSize: 19)
let tx2 = UILabel()
tx2.text = "This is a long sentence to check whether the view and the stackview adapt successfully to the length of this label."
//tx2.numberOfLines = 0
stacktmp.addArrangedSubview(tx)
stacktmp.addArrangedSubview(tx2)
parentview.addSubview(stacktmp)
stacktmp.translatesAutoresizingMaskIntoConstraints = false
print(parentview.frame.size.height)
stacktmp.topAnchor.constraint(equalTo: parentview.topAnchor).isActive = true
stacktmp.heightAnchor.constraint(equalTo: parentview.heightAnchor).isActive = true
mystack.addArrangedSubview(parentview)
stacktmp.trailingAnchor.constraint(equalTo: parentview.trailingAnchor, constant: 0).isActive = true
stacktmp.leadingAnchor.constraint(equalTo: parentview.leadingAnchor, constant: 0).isActive = true
我得到了什么:
我的目标:
如果需要,我希望第二个标签的句子将单词分开并在下面多行填写。
我尝试添加以下行:tx2.numberOfLines = 0(在代码中注释)
结果我得到了:
它确实按照我的意愿拆分了句子,但现在第一个标签不必要地扩展了。
如何在保持第一个标签尽可能窄的同时允许第二个标签在必要时使用多行?我已经尝试修复这个问题几个小时了,已经尝试更改约束,但我仍然无法修复它。
【问题讨论】:
您要查找的内容称为 HuggingPriority 和 CompressionResistance。一开始可能很难理解,但是有很多博客文章可以让它更容易 - 只需谷歌它。 【参考方案1】:如前所述,拥抱和抗压优先级是有帮助的(需要)。
这应该可以得到你想要的:
override func viewDidLoad()
super.viewDidLoad()
// create parentview
let parentview = UIView()
parentview.translatesAutoresizingMaskIntoConstraints = false
parentview.backgroundColor = UIColor.cyan
// add parentview to view
view.addSubview(parentview)
// constrain parentview to Zero all the way around
parentview.topAnchor.constraint(equalTo: view.topAnchor, constant: 0.0).isActive = true
parentview.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 0.0).isActive = true
parentview.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0.0).isActive = true
parentview.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 0.0).isActive = true
// create stack view
let stacktmp = UIStackView()
stacktmp.translatesAutoresizingMaskIntoConstraints = false
stacktmp.axis = .horizontal
// add stack view to parentview
parentview.addSubview(stacktmp)
// constrain stack view top / leading / trailing at Zero, height equal to parentview height
stacktmp.topAnchor.constraint(equalTo: parentview.topAnchor, constant: 0.0).isActive = true
stacktmp.leadingAnchor.constraint(equalTo: parentview.leadingAnchor, constant: 0.0).isActive = true
stacktmp.trailingAnchor.constraint(equalTo: parentview.trailingAnchor, constant: 0.0).isActive = true
stacktmp.heightAnchor.constraint(equalTo: parentview.heightAnchor).isActive = true
// create "left" label
let tx = UILabel()
tx.text = "ss"
tx.backgroundColor = UIColor.red
tx.font = UIFont.boldSystemFont(ofSize: 19)
// set Content Hugging to 252
tx.setContentHuggingPriority(UILayoutPriority(rawValue: 252), for: .horizontal)
// set Content Compression Resistance to 1000
tx.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 1000), for: .horizontal)
// create "right" label
let tx2 = UILabel()
tx2.text = "This is a long sentence to check whether the view and the stackview adapt successfully to the length of this label."
// Zero lines, to get word wrapping
tx2.numberOfLines = 0
// set Content Hugging to 252
tx2.setContentHuggingPriority(UILayoutPriority(rawValue: 252), for: .horizontal)
// set Content Compression Resistance to 1000
tx2.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 1000), for: .horizontal)
// add labels to stack view
stacktmp.addArrangedSubview(tx)
stacktmp.addArrangedSubview(tx2)
结果:
【讨论】:
【参考方案2】:试试这个
import UIKit
class stackQueryVC: UIViewController
/// Width Height
let height = UIScreen.main.bounds.height
let width = UIScreen.main.bounds.width
private var mainStackView: UIStackView?
private var internalView1: UIView?
private var internalView2: UIView?
private var label1 : UILabel?
private var label2 : UILabel?
override func viewDidLoad()
super.viewDidLoad()
// Do any additional setup after loading the view.
DispatchQueue.main.async
self.addStackView()
func addStackView()
mainStackView = UIStackView()
internalView1 = UIView()
internalView2 = UIView()
label1 = UILabel()
label2 = UILabel()
label1?.text = "ios-geek"
label2?.text = "qwerykgasgdasgdhgashdgjasgdasgdjahsdjahsgdasdjagsjdahsgdjsdhasd"
label1?.numberOfLines = 0
label2?.numberOfLines = 0
label1?.textColor = UIColor.black
label2?.textColor = UIColor.black
/// Set Translation Properties
mainStackView?.translatesAutoresizingMaskIntoConstraints = false
internalView1?.translatesAutoresizingMaskIntoConstraints = false
internalView2?.translatesAutoresizingMaskIntoConstraints = false
label1?.translatesAutoresizingMaskIntoConstraints = false
label2?.translatesAutoresizingMaskIntoConstraints = false
addContentView()
func addContentView()
/// Add Stack View Constraints
mainStackView?.backgroundColor = UIColor.white
self.view.addSubview(mainStackView!)
mainStackView?.topAnchor.constraint(equalTo: self.view.topAnchor).isActive=true
mainStackView?.leadingAnchor.constraint(equalTo: self.view.leadingAnchor).isActive=true
mainStackView?.trailingAnchor.constraint(equalTo: self.view.trailingAnchor).isActive=true
mainStackView?.bottomAnchor.constraint(equalTo: self.view.bottomAnchor).isActive=true
/// Add First StackView
mainStackView?.distribution = .fillEqually
mainStackView?.axis = .horizontal
mainStackView?.alignment = .center
mainStackView?.spacing = 10
mainStackView?.backgroundColor = UIColor.white
/// View Properties
internalView1?.backgroundColor = .red
internalView2?.backgroundColor = .purple
/// Add Views
mainStackView?.addArrangedSubview(internalView1!)
internalView1?.topAnchor.constraint(equalTo: mainStackView!.topAnchor).isActive=true
internalView1?.bottomAnchor.constraint(equalTo: mainStackView!.bottomAnchor).isActive=true
internalView1?.leadingAnchor.constraint(equalTo: mainStackView!.leadingAnchor).isActive=true
mainStackView?.addArrangedSubview(internalView2!)
internalView2?.leadingAnchor.constraint(equalTo: internalView1!.trailingAnchor).isActive=true
internalView2?.bottomAnchor.constraint(equalTo: internalView1!.bottomAnchor).isActive=true
internalView2?.topAnchor.constraint(equalTo: internalView1!.topAnchor).isActive=true
/// Add Labels
internalView1?.addSubview(label1!)
label1?.topAnchor.constraint(equalTo: internalView1!.topAnchor).isActive=true
label1?.bottomAnchor.constraint(equalTo: internalView1!.bottomAnchor).isActive=true
label1?.leadingAnchor.constraint(equalTo: internalView1!.leadingAnchor).isActive=true
label1?.trailingAnchor.constraint(equalTo: internalView1!.trailingAnchor).isActive=true
internalView2?.addSubview(label2!)
label2?.topAnchor.constraint(equalTo: internalView2!.topAnchor).isActive=true
label2?.bottomAnchor.constraint(equalTo: internalView2!.bottomAnchor).isActive=true
label2?.leadingAnchor.constraint(equalTo: internalView2!.leadingAnchor).isActive=true
label2?.trailingAnchor.constraint(equalTo: internalView2!.trailingAnchor).isActive=true
选项2如果你只想直接添加UILabels
private var totalNumberOfLabels : Int?
func addStackView()
mainStackView = UIStackView()
label1 = UILabel()
label2 = UILabel()
label1?.text = "ios-geek"
label2?.text = "qwerykgasgdasgdhgashdgjasgdasgdjahsdjahsgdasdjagsjdahsgdjsdhasd"
label1?.numberOfLines = 0
label2?.numberOfLines = 0
label1?.textColor = UIColor.black
label2?.textColor = UIColor.black
label1?.backgroundColor = .red
label2?.backgroundColor = .purple
/// Set Translation Properties
mainStackView?.translatesAutoresizingMaskIntoConstraints = false
label1?.translatesAutoresizingMaskIntoConstraints = false
label2?.translatesAutoresizingMaskIntoConstraints = false
addContentView()
func addContentView()
/// Add Stack View Constraints
mainStackView?.backgroundColor = UIColor.white
self.view.addSubview(mainStackView!)
mainStackView?.topAnchor.constraint(equalTo: self.view.topAnchor).isActive=true
mainStackView?.leadingAnchor.constraint(equalTo: self.view.leadingAnchor).isActive=true
mainStackView?.trailingAnchor.constraint(equalTo: self.view.trailingAnchor).isActive=true
mainStackView?.bottomAnchor.constraint(equalTo: self.view.bottomAnchor).isActive=true
/// Add First StackView
mainStackView?.distribution = .fillEqually
mainStackView?.axis = .horizontal
mainStackView?.alignment = .center
mainStackView?.spacing = 10
mainStackView?.backgroundColor = UIColor.white
/// Add Views
mainStackView?.addArrangedSubview(label1!)
label1?.topAnchor.constraint(equalTo: mainStackView!.topAnchor).isActive=true
label1?.bottomAnchor.constraint(equalTo: mainStackView!.bottomAnchor).isActive=true
label1?.leadingAnchor.constraint(equalTo: mainStackView!.leadingAnchor).isActive=true
label1?.widthAnchor.constraint(equalToConstant: width/CGFloat(totalNumberOfLabels!)).isActive=true
mainStackView?.addArrangedSubview(label2!)
label2?.topAnchor.constraint(equalTo: label1!.topAnchor).isActive=true
label2?.bottomAnchor.constraint(equalTo: label1!.bottomAnchor).isActive=true
label2?.leadingAnchor.constraint(equalTo: label1!.trailingAnchor).isActive=true
label1?.widthAnchor.constraint(equalToConstant: width/CGFloat(totalNumberOfLabels!)).isActive=true
输出
【讨论】:
以上是关于无法以编程方式在 Swift 的堆栈视图中正确排列两个标签的主要内容,如果未能解决你的问题,请参考以下文章
在 Swift 中以编程方式将视图添加到 stackview
Swift - StackView 和添加约束,以编程方式添加视图到堆栈 - 加载后调整单元格高度?