Пользовательских этикеток, которая изменяет По его Содержимому
Я делаю ярлык с нуля. (Моя цель состоит в том, чтобы сделать вертикальную текстовую метку для монгольского скрипта, но пока я просто делаю обычную горизонтальную текстовую метку как практику.)Как сделать кадр пользовательского представления в соответствии его instrinsic размера содержимого
До тех пор, пока нет ограничений длины и ширины, фрейма метки для изменения размера в соответствии с его внутренним размером содержимого.
Он работает в IB
В IB все, кажется, работает хорошо, когда я испытываю UILabel
, мой заказ ярлык (а UIView
подкласс), и кнопка.
Я добавляю верхние и ведущие ограничения для каждого из этих видов, но не устанавливаю ограничений по высоте или ширине.
Если я изменить их на раскадровке (но без добавления каких-либо ограничений) больше ...
И затем выберите Frames Update для Все Представления в View Контроллер, нормальная метка и мой пользовательский ярлык, как правильно изменяются, так и сами по себе.
Это не работает на Running App
При изменении текста метки во время выполнения, хотя, рамки моего пользовательского ярлыка не изменение размера. (Я временно добавил темно-синюю границу к текстовому слою, чтобы помочь отличить его здесь от рамы на заказ ярлык, который является светло-голубой цвет фона.)
Нажатие кнопки «Изменить текст» дает
Как вы можете видеть, рама текстового слоя изменилась, но кадр пользовательского представления не сделал.
Код
Это мой класс на заказ ярлык:
import UIKit
@IBDesignable
class UILabelFromScratch: UIView {
private let textLayer = CATextLayer()
@IBInspectable var text: String = "" {
didSet {
updateTextLayerFrame()
}
}
@IBInspectable var fontSize: CGFloat = 17 {
didSet {
updateTextLayerFrame()
}
}
// MARK: - Initialization
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
setup()
}
func setup() {
// Text layer
textLayer.borderColor = UIColor.blueColor().CGColor
textLayer.borderWidth = 1
textLayer.contentsScale = UIScreen.mainScreen().scale
layer.addSublayer(textLayer)
}
// MARK: Other methods
override func intrinsicContentSize() -> CGSize {
return textLayer.frame.size
}
func updateTextLayerFrame() {
let myAttribute = [ NSFontAttributeName: UIFont.systemFontOfSize(fontSize) ]
let attrString = NSMutableAttributedString(string: self.text, attributes: myAttribute)
let size = dimensionsForAttributedString(attrString)
textLayer.frame = CGRect(x: self.layer.bounds.origin.x, y: self.layer.bounds.origin.y, width: size.width, height: size.height)
textLayer.string = attrString
}
func dimensionsForAttributedString(attrString: NSAttributedString) -> CGSize {
var ascent: CGFloat = 0
var descent: CGFloat = 0
var width: CGFloat = 0
let line: CTLineRef = CTLineCreateWithAttributedString(attrString)
width = CGFloat(CTLineGetTypographicBounds(line, &ascent, &descent, nil))
// make width an even integer for better graphics rendering
width = ceil(width)
if Int(width)%2 == 1 {
width += 1.0
}
return CGSize(width: width, height: ceil(ascent+descent))
}
}
А вот класс вид контроллера:
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var normalLabel: UILabel!
@IBOutlet weak var labelFromScratch: UILabelFromScratch!
@IBAction func changeTextButtonTapped(sender: UIButton) {
normalLabel.text = "Hello"
labelFromScratch.text = "Hello"
}
}
Вопрос
Что это такое, что UILabel
делает это Я отсутствую в своем пользовательском ярлыке? I overrode intrinsicContentSize
:
override func intrinsicContentSize() -> CGSize {
return textLayer.frame.size
}
Что еще мне нужно сделать?