Я копирую тот же вопрос, заданный перед Question. Я пробовал данные решения и не смог его решить, так как sizetofit не был эффективным, когда я использую Autolayout.
Ожидаемый дисплей выглядит следующим образом.
Я копирую тот же вопрос, заданный перед Question. Я пробовал данные решения и не смог его решить, так как sizetofit не был эффективным, когда я использую Autolayout.
Ожидаемый дисплей выглядит следующим образом.
Edit
В моем первоначальном ответе я использовал стиль абзаца метки. Оказывается, для многострочных меток это фактически мешает ярлыку быть многострочным. В результате я удалил его из расчета. Подробнее об этом можно узнать в Github
Для тех из вас, кто более удобен в использовании Open Source, определенно посмотрите TTTAttributedLabel, где вы можете установить выравнивание текста меток на TTTAttributedLabelVerticalAlignmentTop
Трюк заключается в подклассе UILabel
и переопределении drawTextInRect
. Затем убедитесь, что текст нарисован в начале границ метки.
Здесь наивная реализация, которую вы можете использовать прямо сейчас:
@IBDesignable class TopAlignedLabel: UILabel {
override func drawTextInRect(rect: CGRect) {
if let stringText = text {
let stringTextAsNSString = stringText as NSString
var labelStringSize = stringTextAsNSString.boundingRectWithSize(CGSizeMake(CGRectGetWidth(self.frame), CGFloat.max),
options: NSStringDrawingOptions.UsesLineFragmentOrigin,
attributes: [NSFontAttributeName: font],
context: nil).size
super.drawTextInRect(CGRectMake(0, 0, CGRectGetWidth(self.frame), ceil(labelStringSize.height)))
} else {
super.drawTextInRect(rect)
}
}
override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
layer.borderWidth = 1
layer.borderColor = UIColor.blackColor().CGColor
}
}
@IBDesignable class TopAlignedLabel: UILabel {
override func drawText(in rect: CGRect) {
if let stringText = text {
let stringTextAsNSString = stringText as NSString
let labelStringSize = stringTextAsNSString.boundingRect(with: CGSize(width: self.frame.width,height: CGFloat.greatestFiniteMagnitude),
options: NSStringDrawingOptions.usesLineFragmentOrigin,
attributes: [NSFontAttributeName: font],
context: nil).size
super.drawText(in: CGRect(x:0,y: 0,width: self.frame.width, height:ceil(labelStringSize.height)))
} else {
super.drawText(in: rect)
}
}
override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
layer.borderWidth = 1
layer.borderColor = UIColor.black.cgColor
}
}
IB_DESIGNABLE
@interface TopAlignedLabel : UILabel
@end
@implementation TopAlignedLabel
- (void)drawTextInRect:(CGRect)rect {
if (self.text) {
CGSize labelStringSize = [self.text boundingRectWithSize:CGSizeMake(CGRectGetWidth(self.frame), CGFLOAT_MAX)
options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading
attributes:@{NSFontAttributeName:self.font}
context:nil].size;
[super drawTextInRect:CGRectMake(0, 0, ceilf(CGRectGetWidth(self.frame)),ceilf(labelStringSize.height))];
} else {
[super drawTextInRect:rect];
}
}
- (void)prepareForInterfaceBuilder {
[super prepareForInterfaceBuilder];
self.layer.borderWidth = 1;
self.layer.borderColor = [UIColor blackColor].CGColor;
}
@end
Поскольку я использовал IBDesignable, вы можете добавить этот ярлык в раскадровку и посмотреть, как это происходит, вот что мне кажется.
Если вы не ограничены наличием UILabel фиксированного размера, вместо выравнивания текста внутри UILabel просто используйте ограничение ≥ на данной метке, чтобы изменить его размер.
Это самое элегантное решение, использующее Auto Layout. Однако не забудьте установить numOfLines на ноль.
Вы можете использовать UITextView вместо UILabel:
Снимите флажок "Прокрутка включена"
Снимите флажок "Редактируемый"
Снимите флажок "Выбор"
Установите цвет фона в ClearColor
У меня была та же проблема, и я решил это. Я только что отредактировал базовый уровень в разделе Attribute Inspector для метки. Установите его в положение "Выровнять центры".
Вместо этого я изменил нижнюю константу пространства на приоритет @250 и решил свою проблему. И моя метка имеет постоянную высоту с <= constant
Вы сделали бы это, удалив минимальную высоту.
Если вам нужна минимальная высота для чего-то еще ниже метки, вы должны использовать представление контейнера, размер которого изменился на основе содержимого метки, но использовался минимум.
Автоматическая компоновка работает только с краями/размерами контроллера, а не с контроллерами content.so не рекомендуется использовать автоматический макет, чтобы отображать текст ярлыка поверх первой строки. согласно мне sizetofit - лучший вариант для этого.
Я использовал решение @Daniel Golasko, и всякий раз, когда текст внутри UILabel был длиннее, чем может содержать UILabel, текст начнет перемещаться вниз, а не оставаться выровненным вверх.
Я изменил эту строку, чтобы убедиться, что текст правильно выровнен.
[super drawTextInRect:CGRectMake(0, 0, ceilf(CGRectGetWidth(self.frame)),MIN(ceilf(labelStringSize.height), self.frame.size.height))];
У меня была аналогичная проблема, в которой было 3 ярлыка. Средняя метка могла бы иметь гораздо более длинный текст, чем два других, поэтому его высота могла бы стать намного больше.
Вот так:
Я установил ограничение нижнего пространства средней метки как >= нижнюю метку.
Это решило мою проблему.
Вы можете попробовать, если кнопка [button setContentVerticalAlignment:UIControlContentVerticalAlignmentTop];
Изменить:
Вы можете попробовать это, если хотите использовать только метку:
Для меня я не установил ограничение по высоте, текст всегда растет с вершины метки. Ограничения для этой метки - сверху, слева, справа. Кстати, у моей метки есть фиксированные номера строк, поэтому не беспокойтесь о высоте.
@IBInspectable var alignTop: Bool = false
func setAlignTop() {
let text = self.text!
let lines = text.characters.split(separator: "\n").count
if lines < self.numberOfLines {
var newLines = ""
for _ in 0..<(self.numberOfLines - lines) {
newLines = newLines.appending("\n ")
}
self.text! = text.appending(newLines)
}
}
override var text: String? {
didSet {
if alignTop {
self.setAlignTop()
}
}
}
Здесь улучшается решение Swift 3 от Daniel Galasko (здесь вы также можете установить максимальное количество строк без смещения сверху):
import UIKit
@IBDesignable class TopAlignedLabel: UILabel {
override func drawText(in rect: CGRect) {
if let stringText = text {
let stringTextAsNSString = stringText as NSString
let labelString = stringTextAsNSString.boundingRect(with: CGSize(width: frame.width, height: .greatestFiniteMagnitude),
options: .usesLineFragmentOrigin, attributes: [NSFontAttributeName: font], context: nil)
super.drawText(in: CGRect(x: 0, y: 0, width: frame.width, height: ceil(labelString.size.height) > frame.height ? frame.height : ceil(labelString.size.height)))
} else {
super.drawText(in: rect)
}
}
override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
layer.borderWidth = 1
layer.borderColor = UIColor.black.cgColor
}
}
Существует простое решение для случаев, когда высота метки не обязательно должна быть постоянной: поставьте Label
в Stack View
. Не забудьте добавить указатели на начало и конец в Stack View
. Вот скриншот о том, как это сделать в раскадровке:
используйте этот класс, вы можете изменить alignment
текста с помощью contentMode
.
Поддерживаемый случай:.top,.bottom,.left,.right,.topLeft,.topRight,.bottomLeft,.bottomRight
Swift4
import Foundation
import UIKit
@IBDesignable
class UIAlignedLabel: UILabel {
override func drawText(in rect: CGRect) {
if let text = text as NSString? {
func defaultRect(for maxSize: CGSize) -> CGRect {
let size = text
.boundingRect(
with: maxSize,
options: NSStringDrawingOptions.usesLineFragmentOrigin,
attributes: [
NSAttributedStringKey.font: font
],
context: nil
).size
let rect = CGRect(
origin: .zero,
size: CGSize(
width: min(frame.width, ceil(size.width)),
height: min(frame.height, ceil(size.height))
)
)
return rect
}
switch contentMode {
case .top, .bottom, .left, .right, .topLeft, .topRight, .bottomLeft, .bottomRight:
let maxSize = CGSize(width: frame.width, height: frame.height)
var rect = defaultRect(for: maxSize)
switch contentMode {
case .bottom, .bottomLeft, .bottomRight:
rect.origin.y = frame.height - rect.height
default: break
}
switch contentMode {
case .right, .topRight, .bottomRight:
rect.origin.x = frame.width - rect.width
default: break
}
super.drawText(in: rect)
default:
super.drawText(in: rect)
}
} else {
super.drawText(in: rect)
}
}
}
Вы должны подклассифицировать UILabel и переопределить отображение текстового отображения.
class UITopAlignedLabel: UILabel {
override func drawText(in rect: CGRect) {
guard let string = text else {
super.drawText(in: rect)
return
}
let size = (string as NSString).boundingRect(
with: CGSize(width: rect.width, height: .greatestFiniteMagnitude),
options: [.usesLineFragmentOrigin],
attributes: [.font: font],
context: nil).size
var rect = rect
rect.size.height = size.height.rounded()
super.drawText(in: rect)
}
}