У меня есть простой пользовательский UIView (вид с белым фоном на снимке экрана) с использованием xib и настраиваемого класса, производного от UIView.

Custom view

Внутри у меня есть UILabel и кнопка на той же строке, и все.

Размер кнопки фиксированный. Ширина метки должна регулироваться в зависимости от ее содержимого.

Я бы хотел: - подогнать размер метки к ее содержимому - установить положение кнопки всегда сразу после метки - подогнать кастом к ее содержимому

Так :

Correct Cutsom view

Как я могу это сделать?

Добавить контент:

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:

UILabel contraints

Отметьте ограничения UIButton:

enter image description here

3
gduh 24 Сен 2018 в 15:58

2 ответа

Лучший ответ

Благодаря @matt я нашел решение.

В моем коде было всего 2 ошибки.

  1. Следующий код строки translatesAutoresizingMaskIntoConstraints = false в моем пользовательском представлении отсутствовал, поэтому intrinsicContentSize никогда не вызывался.
  2. Как предложил @matt, внутри intrinsicContentSize мне нужно предоставить значение, основанное на внутренней ширине метки и кнопки для параметров ширины вместо UIViewNoIntrinsicMetric

Теперь правильный код:

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
}

}
0
gduh 24 Сен 2018 в 14:39

Следующее расширение можно использовать для расчета высоты и ширины метки.

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)
}

}

В вашем случае, поскольку размер кнопки фиксирован, вы можете рассчитать ширину метки, используя указанное выше расширение, и ее можно использовать для установки ограничения ширины всего представления. Если ваша метка имеет начальное ограничение 8 и конечное ограничение 8 для кнопки, а кнопка имеет конечное ограничение 8 для представления контейнера, вы можете рассчитать требуемую ширину для своего представления как:

viewWidthConstraint.constant = 8+<width of string from the above extension>+8+<width of button>+8

Здесь единственным изменяющимся параметром будет ширина метки.

0
Naveen George Thoppan 24 Сен 2018 в 13:52