我有一个草图,我正在尝试以编程方式实现这一概念。
这是我的素描:
我的代码:
let luna = UIView()
let descStrWidth = messageDescription.stringWidth // Using String Extension i made.
let descStrHeight = messageDescription.stringHeight // Using String Extension i made.
let titleStrHeight = messageTitle.stringHeight // ..
let titleStrWidth = messageTitle.stringWidth // ..
let titleLabel = UILabel()
titleLabel.text = messageTitle
titleLabel.font = UIFont(name: "avenirnext-demibold", size: 13)
titleLabel.textColor = UIColor(hexString: "4A4A4A")
titleLabel.numberOfLines = 0 // whole idea of self-sizing
let titleDesc = UILabel()
titleDesc.text = messageDescription
titleDesc.font = UIFont(name: "avenirnext-regular", size: 9)
titleDesc.textColor = UIColor(hexString: "4A4A4A")
titleDesc.numberOfLines = 0
// My mainView
luna.frame = CGRect(x: 16, y: 40, width: screenWidth - 30, height: titleStrHeight + descStrHeight)
luna.center.x = luna.center.x
luna.backgroundColor = .white
luna.addShadow(radius: 11, opacity: 0.2) // Some Shadow
luna.layer.cornerRadius = 10
titleDesc.frame = CGRect(x: luna.frame.minX + 3, y: titleLabel.frame.maxY + titleStrHeight, width: luna.frame.width, height: descStrHeight)
titleLabel.frame = CGRect(x: luna.frame.minX + 3, y: 8, width: titleStrWidth, height: titleStrHeight)
luna.addSubview(titleLabel)
luna.addSubview(titleDesc)
self.view.addSubview(luna)
获取提供的字符串宽度和高度:
extension String {
var stringWidth: CGFloat {
let constraintRect = CGSize(width: UIScreen.main.bounds.width, height: .greatestFiniteMagnitude)
let boundingBox = self.trimmingCharacters(in: .whitespacesAndNewlines).boundingRect(with: constraintRect, options: [.usesLineFragmentOrigin, .usesFontLeading], attributes: [NSAttributedStringKey.font: UIFont.systemFont(ofSize: 14)], context: nil)
return boundingBox.width
}
var stringHeight: CGFloat {
let constraintRect = CGSize(width: UIScreen.main.bounds.width, height: .greatestFiniteMagnitude)
let boundingBox = self.trimmingCharacters(in: .whitespacesAndNewlines).boundingRect(with: constraintRect, options: [.usesLineFragmentOrigin, .usesFontLeading], attributes: [NSAttributedStringKey.font: UIFont.systemFont(ofSize: 14)], context: nil)
return boundingBox.height
}
}
这是我到目前为止所取得的成就。受约束可能会更容易,对吧?
答案 0 :(得分:1)
这是使用自动布局和堆栈视图的解决方案。
let luna = UIView()
let titleLabel = UILabel()
titleLabel.text = "Title"
titleLabel.font = UIFont(name: "avenirnext-demibold", size: 13)
//titleLabel.textColor = UIColor(hexString: "4A4A4A")
titleLabel.numberOfLines = 0 // whole idea of self-sizing
let titleDesc = UILabel()
titleDesc.text = "Description"
titleDesc.font = UIFont(name: "avenirnext-regular", size: 9)
//titleDesc.textColor = UIColor(hexString: "4A4A4A")
titleDesc.numberOfLines = 0
// My mainView
luna.backgroundColor = .white
//luna.addShadow(radius: 11, opacity: 0.2) // Some Shadow
luna.layer.cornerRadius = 10
let verticalStackView = UIStackView(arrangedSubviews: [titleLabel, titleDesc])
verticalStackView.axis = .vertical
let okButton = UIButton()
okButton.setTitleColor(.blue, for: .normal)
okButton.setTitle("Okay", for: .normal)
okButton.setContentHuggingPriority(.defaultHigh, for: .horizontal) // to stretch the okay button horizontally
let horizontalStackView = UIStackView(arrangedSubviews: [verticalStackView, okButton])
horizontalStackView.axis = .horizontal
luna.addSubview(horizontalStackView)
view.addSubview(luna)
horizontalStackView.translatesAutoresizingMaskIntoConstraints = false // when using autolayout from code, this property must be false, otherwise constraint won't work
luna.translatesAutoresizingMaskIntoConstraints = false
// This method activates all constraint (when you create a constraint with anchors, by default they are disabled)
NSLayoutConstraint.activate([
horizontalStackView.topAnchor.constraint(equalTo: luna.topAnchor, constant: 8),
horizontalStackView.bottomAnchor.constraint(equalTo: luna.bottomAnchor, constant: -8),
horizontalStackView.leadingAnchor.constraint(equalTo: luna.leadingAnchor, constant: 8),
horizontalStackView.trailingAnchor.constraint(equalTo: luna.trailingAnchor, constant: -8),
luna.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 30),
luna.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 30),
luna.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -30)
])
您可以通过更改堆栈视图的spacing
属性来更改视图之间的距离。 (即horizontalStackView.spacing = 16
在两个标签和“确定”按钮之间放置16点的空间)
答案 1 :(得分:0)
您可以尝试
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let luna = UIView()
let titleLabel = UILabel()
titleLabel.text = "messageTitle"
titleLabel.font = UIFont(name: "avenirnext-demibold", size: 13)
titleLabel.textColor = UIColor.blue
titleLabel.numberOfLines = 0 // whole idea of self-sizing
let titleDesc = UILabel()
titleDesc.text = "messageDescriptionmessageDescriptionmessageDescriptionmessageDescriptionmessageDescriptionmessageDescriptionmessageDescriptionvmessageDescriptionmessageDescriptionmessageDescription"
titleDesc.font = UIFont(name: "avenirnext-regular", size: 9)
titleDesc.textColor = UIColor.red
titleDesc.numberOfLines = 0
let btn = UIButton()
btn.setTitle("Okay", for: .normal)
btn.setTitleColor(UIColor.blue, for: .normal)
luna.translatesAutoresizingMaskIntoConstraints = false
titleLabel.translatesAutoresizingMaskIntoConstraints = false
titleDesc.translatesAutoresizingMaskIntoConstraints = false
btn.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(luna)
luna.layer.cornerRadius = 10
luna.addSubview(titleLabel)
luna.addSubview(titleDesc)
luna.addSubview(btn)
luna.layer.borderColor = UIColor.green.cgColor
luna.layer.borderWidth = 2
btn.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 1000), for: .horizontal)
NSLayoutConstraint.activate([
luna.topAnchor.constraint(equalTo: view.topAnchor, constant: 30),
luna.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),
luna.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20),
titleLabel.topAnchor.constraint(equalTo: luna.topAnchor, constant: 20),
titleLabel.leadingAnchor.constraint(equalTo: luna.leadingAnchor, constant: 20),
titleLabel.trailingAnchor.constraint(equalTo: btn.leadingAnchor, constant: -10),
titleDesc.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 10),
titleDesc.leadingAnchor.constraint(equalTo: luna.leadingAnchor, constant: 20),
titleDesc.trailingAnchor.constraint(equalTo: btn.leadingAnchor, constant: -10),
titleDesc.bottomAnchor.constraint(equalTo: luna.bottomAnchor, constant: -20),
btn.centerYAnchor.constraint(equalTo: luna.centerYAnchor, constant: 0 ),
btn.trailingAnchor.constraint(equalTo: luna.trailingAnchor, constant: -20),
])
}
答案 2 :(得分:0)
正如人们所说,我建议您将来考虑使用自动布局,但是现在这应该可以满足您的要求:
let luna = UIView()
let titleLabel = UILabel()
titleLabel.text = messageTitle
titleLabel.font = UIFont(name: "avenirnext-demibold", size: 13)
titleLabel.textColor = UIColor(hexString: "4A4A4A")
titleLabel.numberOfLines = 0 // whole idea of self-sizing
let titleDesc = UILabel()
titleDesc.text = messageDescription
titleDesc.font = UIFont(name: "avenirnext-regular", size: 9)
titleDesc.textColor = UIColor(hexString: "4A4A4A")
titleDesc.numberOfLines = 0
// My mainView
// The margins of the labels inside the luna view.
let margins = UIEdgeInsetsMake(8, 4, 8, 4)
// The vertical space between the two labels.
let labelSpace: CGFloat = 4
let titleDescSize = titleDesc.sizeThatFits(CGSize(width: screenWidth - 30 - margins.left - margins.right, height: .greatestFiniteMagnitude))
let titleLabelSize = titleLabel.sizeThatFits(CGSize(width: screenWidth - 30 - margins.left - margins.right, height: .greatestFiniteMagnitude))
luna.frame = CGRect(x: 16, y: 40, width: screenWidth - 30, height: titleLabelSize.height + titleDescSize.height + margins.top + margins.bottom + labelSpace)
luna.center.x = luna.center.x
luna.backgroundColor = .white
luna.layer.borderWidth = luna.addShadow(radius: 11, opacity: 0.2) // Some Shadow
luna.layer.cornerRadius = 10
titleLabel.frame = CGRect(x: margins.left, y: margins.top, width: titleLabelSize.width, height: titleLabelSize.height)
titleDesc.frame = CGRect(x: margins.left, y: titleLabel.frame.origin.y + titleLabel.frame.size.height + labelSpace, width: titleDescSize.width, height: titleDescSize.height)
luna.addSubview(titleLabel)
luna.addSubview(titleDesc)
self.view.addSubview(luna)
注意:您甚至不需要使用字符串扩展名,因为UILabels
能够根据其当前设置来计算所需的大小。
答案 3 :(得分:0)
您正在使用 avenirnext-demibold 和 avenirnext-regular 自定义字体。但是,在计算字符串的宽度和高度时,您使用的是系统字体 UIFont.systemFont(ofSize:14)。您没有得到正确的字符串宽度和高度。对于 Padding ,titleLabel和titleDesc两个标签的宽度均应小于luna宽度。