我已经快速创建了一个自定义视图,并试图使其正确显示。它本质上是材料卡,可以通过按“更多”按钮来扩展视图。指定底部约束时出现我的问题。它是必需的,但设置它可以扩展我的自定义视图。
我已经在android中实现了它,我想我正在寻找android:height='wrap_content'
的类似物。我尝试设置纵横比约束,以使视图保持适当的大小,但阻止自定义视图在其子视图更改时扩展。另外,我尝试使用lessThanOrEqualTo约束,但这太模糊了,无法满足底部约束。
这是我的UIExpandableCard视图的样子:
import Foundation
import MaterialComponents
@IBDesignable
public class UIExpandableCard: UIView {
// attributes
@IBInspectable var overlineText: String? {
didSet {
overlineLabel.text = overlineText?.uppercased()
}
}
@IBInspectable var headlineText: String? {
didSet {
headlineLabel.text = headlineText
}
}
@IBInspectable var bodyText: String? {
didSet {
bodyLabel.text = bodyText
}
}
@IBInspectable var logoImage: UIImage? {
didSet {
logoImageView.image = logoImage
}
}
var cardView: MDCCard!
var overlineLabel: UILabel!
var headlineLabel: UILabel!
var bodyLabel: UILabel!
var moreButton: UIButton!
var logoImageView: UIImageView!
var isCardExpanded = false
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setup()
}
private func setup() {
self.translatesAutoresizingMaskIntoConstraints = false
setupViews()
setupConstraints()
}
private func setupViews() {
self.clipsToBounds = true
cardView = MDCCard(frame: CGRect.zero)
cardView.translatesAutoresizingMaskIntoConstraints = false
cardView.isInteractable = false
self.addSubview(cardView)
overlineLabel = UILabel(frame: CGRect.zero)
overlineLabel.translatesAutoresizingMaskIntoConstraints = false
overlineLabel.font = UIFont.preferredFont(forTextStyle: .footnote)
overlineLabel.text = overlineText?.uppercased()
self.addSubview(overlineLabel)
headlineLabel = UILabel(frame: CGRect.zero)
headlineLabel.translatesAutoresizingMaskIntoConstraints = false
headlineLabel.font = UIFont.preferredFont(forTextStyle: .title1)
headlineLabel.text = headlineText
self.addSubview(headlineLabel)
bodyLabel = UILabel(frame: CGRect.zero)
bodyLabel.translatesAutoresizingMaskIntoConstraints = false
bodyLabel.font = UIFont.preferredFont(forTextStyle: .body)
bodyLabel.numberOfLines = 1
bodyLabel.text = bodyText
self.addSubview(bodyLabel)
logoImageView = UIImageView(image: logoImage)
logoImageView.translatesAutoresizingMaskIntoConstraints = false
logoImageView.contentMode = .scaleAspectFit
self.addSubview(logoImageView)
moreButton = UIButton(type: .roundedRect)
moreButton.isUserInteractionEnabled = true
moreButton.translatesAutoresizingMaskIntoConstraints = false
moreButton.setTitle("More", for: .normal)
moreButton.addTarget(self, action: #selector(buttonClicked), for: .touchUpInside)
self.addSubview(moreButton)
}
@objc func buttonClicked(_ sender: UIButton) {
if !isCardExpanded {
moreButton.setTitle("Less", for: .normal)
bodyLabel.numberOfLines = 0
} else {
moreButton.setTitle("More", for: .normal)
bodyLabel.numberOfLines = 1
}
isCardExpanded = !isCardExpanded
}
private func setupConstraints() {
NSLayoutConstraint.activate([
cardView.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 8),
cardView.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -8),
cardView.topAnchor.constraint(equalTo: self.topAnchor, constant: 8),
cardView.bottomAnchor.constraint(lessThanOrEqualTo: self.bottomAnchor, constant: -8),
overlineLabel.leadingAnchor.constraint(equalTo: cardView.leadingAnchor, constant: 16),
overlineLabel.topAnchor.constraint(equalTo: cardView.topAnchor, constant: 16),
headlineLabel.leadingAnchor.constraint(equalTo: cardView.leadingAnchor, constant: 16),
headlineLabel.topAnchor.constraint(equalTo: overlineLabel.bottomAnchor, constant: 8),
NSLayoutConstraint(item: logoImageView, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 48),
NSLayoutConstraint(item: logoImageView, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 48),
logoImageView.trailingAnchor.constraint(equalTo: cardView.trailingAnchor, constant: -16),
logoImageView.topAnchor.constraint(equalTo: cardView.topAnchor, constant: 16),
bodyLabel.leadingAnchor.constraint(equalTo: cardView.leadingAnchor, constant: 16),
bodyLabel.topAnchor.constraint(equalTo: logoImageView.bottomAnchor, constant: 16),
bodyLabel.trailingAnchor.constraint(equalTo: cardView.trailingAnchor, constant: -8),
moreButton.topAnchor.constraint(greaterThanOrEqualTo: bodyLabel.bottomAnchor, constant: 8),
moreButton.leadingAnchor.constraint(equalTo: cardView.leadingAnchor, constant: 16),
moreButton.bottomAnchor.constraint(equalTo: cardView.bottomAnchor, constant: -8)
])
}
}
基本上我想要类似左边的东西。但是,我做对了,其中一个视图(蓝色)正在拉伸以填充约束。
我是iOS的新手,但是有使用android的经验,因此任何与此相关的解释都将有所帮助。
谢谢。
答案 0 :(得分:0)
您无法使用lessThanOrEqualTo
来做到这一点。尽管我无法完全理解您的问题,但希望这种方法能有所帮助。
首先定义流约束,例如:
var heightConstraint: NSLayoutConstraint?
并在setupConstraint中将其替换为底部约束:
private func setupConstraints() {
heightConstraint = cardView.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 1, constant: 0)
NSLayoutConstraint.activate([
cardView.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 8),
cardView.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -8),
cardView.topAnchor.constraint(equalTo: self.topAnchor, constant: 8),
heightConstraint,
overlineLabel.leadingAnchor.constraint(equalTo: cardView.leadingAnchor, constant: 16),
overlineLabel.topAnchor.constraint(equalTo: cardView.topAnchor, constant: 16),
.
.
.
最后按下按钮时:
private func expandViewWithAnimation(_ isExpand: Bool) {
UIView.animate(withDuration: 0.8) {
self.heightConstraint?.constant = isExpand ? 80:0
self.layoutIfNeeded()
}
}
@objc func buttonClicked(_ sender: UIButton) {
if !isCardExpanded {
moreButton.setTitle("Less", for: .normal)
bodyLabel.numberOfLines = 0
} else {
moreButton.setTitle("More", for: .normal)
bodyLabel.numberOfLines = 1
}
expandViewWithAnimation(isCardExpanded)
isCardExpanded = !isCardExpanded
}
由于信誉不足,我无法对您的信息发表评论:)
答案 1 :(得分:0)
因此,我找到了一种解决方案,该解决方案似乎可以满足我的需求。我仍在努力将自己实际想达到的目标包围住。基本上,我想要的是视图高度由其子视图及其约束定义,而不必在约束中指定。同时,我需要满足界面中的高度限制。
我的解决方案如下:在我的界面中,向卡片视图添加低优先级高度限制0。这满足了对场景高度的要求,同时还允许我的视图在不拉伸的情况下展开和收缩。
...整个视图的高度为零的低优先级约束。低优先级约束将尝试缩小程序集,而其他约束则阻止其缩小到足以裁剪其子视图的程度。
我在another stack overflow question上找到了此解决方案。
答案 2 :(得分:-1)
在Joshua's answer之后,我阻止了自定义视图的拉伸:
let width = widthAnchor.constraint(equalToConstant: 0)
width.priority = .defaultLow
width.isActive = true