[英]How to set custom UIView width automatically based on its content?
I have a simple custom UIView (The view with white background on the screenshot) using xib and custom class derived from UIView.我有一个简单的自定义 UIView(屏幕截图上带有白色背景的视图),使用了从 UIView 派生的 xib 和自定义类。
Inside I have a UILabel and a button on the same line ant that's all.在里面我有一个 UILabel 和一个按钮在同一行蚂蚁就是这样。
The size of the button is fixed.按钮的大小是固定的。 The width of the label must be adjusted on its content.
标签的宽度必须根据其内容进行调整。
What I would like is : - fit the size of the label to its content - set the position of the button always just after the label - fit the custom to its content我想要的是: - 使标签的大小适合其内容 - 始终在标签之后设置按钮的位置 - 使自定义适合其内容
Like this :像这样 :
How can I proceed to do this ?我怎样才能继续这样做?
Add content :添加内容:
class Keyword: UIView {
@IBOutlet weak var label: UILabel!
@IBOutlet var contentView: UIView!
override init(frame: CGRect) {
super .init(frame: frame)
commonInit()
}
required init?(coder aDecoder: NSCoder) {
super .init(coder: aDecoder)
commonInit()
}
fileprivate func commonInit() {
Bundle.main.loadNibNamed("Keyword", owner: self, options: nil)
addSubview(contentView)
contentView.frame = self.bounds
}
override var intrinsicContentSize: CGSize {
let height = CGFloat(21)
return CGSize(width: UIViewNoIntrinsicMetric, height: height)
}
/*
// Only override draw() if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
override func draw(_ rect: CGRect) {
// Drawing code
}
*/
}
UILabel contraints : UILabel 限制:
Tick UIButton constraints :勾选 UIButton 约束:
The following extension can be used to calculate the height and width of label.以下扩展名可用于计算标签的高度和宽度。
extension String {
//Calculate height and width for label with string
func height(withConstrainedWidth width: CGFloat, font: UIFont) -> CGFloat {
let constraintRect = CGSize(width: width, height: .greatestFiniteMagnitude)
let boundingBox = self.boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, attributes: [NSAttributedStringKey.font: font], context: nil)
return ceil(boundingBox.height)
}
func width(withConstrainedHeight height: CGFloat, font: UIFont) -> CGFloat {
let constraintRect = CGSize(width: .greatestFiniteMagnitude, height: height)
let boundingBox = self.boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, attributes: [NSAttributedStringKey.font: font], context: nil)
return ceil(boundingBox.width)
}
}
In your case, since the button size is fixed, you can calculate the width of label using the above extension and can be used to set the width constraint of the entire view.在您的情况下,由于按钮大小是固定的,您可以使用上述扩展名计算标签的宽度,并可用于设置整个视图的宽度约束。 If your label has a leading constraint of 8 and a trailing constraint of 8 to the button and the button has a trailing constraint of 8 to the container view, then you can calculate the required width for your view as:
如果您的标签对按钮的前导约束为 8,尾随约束为 8,并且按钮对容器视图的尾随约束为 8,那么您可以计算视图所需的宽度:
viewWidthConstraint.constant = 8+<width of string from the above extension>+8+<width of button>+8
Here the only changing parameter will be the width of the label.这里唯一改变的参数是标签的宽度。
Thanks to @matt, I found the solution.感谢@matt,我找到了解决方案。
There were just 2 errors in my code.我的代码中只有 2 个错误。
translatesAutoresizingMaskIntoConstraints = false
in my custom view was missing, so intrinsicContentSize
was never called.translatesAutoresizingMaskIntoConstraints = false
,因此从未调用过intrinsicContentSize
。intrinsicContentSize
, I need to provide a value based on the intrinsic widths of the label and the button for the width parameters instead of UIViewNoIntrinsicMetric
intrinsicContentSize
,我需要根据标签的固有宽度和按钮的宽度参数而不是UIViewNoIntrinsicMetric
提供一个值Now, the right code is :现在,正确的代码是:
class Keyword: UIView {
@IBOutlet weak var label: UILabel!
@IBOutlet weak var btn: UIButton!
@IBOutlet var contentView: UIView!
override init(frame: CGRect) {
super .init(frame: frame)
commonInit()
}
required init?(coder aDecoder: NSCoder) {
super .init(coder: aDecoder)
commonInit()
}
fileprivate func commonInit() {
translatesAutoresizingMaskIntoConstraints = false
Bundle.main.loadNibNamed("Keyword", owner: self, options: nil)
addSubview(contentView)
contentView.frame = self.bounds
}
override var intrinsicContentSize: CGSize {
let height = btn.frame.size.height
let width = btn.frame.origin.x + btn.frame.size.width
return CGSize(width: width, height: height)
}
// Only override draw() if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
override func draw(_ rect: CGRect) {
// Drawing code
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.