Редактирование
В моем исходном ответе я использовал стиль абзаца маркировки. Оказывается, что для многострочных маркировок это на самом деле препятствует тому, чтобы маркировка была мультилинией. В результате я удалил его из вычисления. Посмотрите больше об этом в , Github
Для тех из Вас более довольный использованием Открытого исходного кода определенно смотрит 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, можно добавить эту маркировку к раскадровке и часам, это идет, это - то, на что это похоже для меня
использование этот мой класс, можно изменить текст 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)
}
}
}
Вот улучшение на Быстрых 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
}
}
@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()
}
}
}
Для меня я не установил ограничение высоты, текст всегда растет от вершины маркировки. Ограничения для этой маркировки являются вершиной, оставленной, право. Между прочим, моя маркировка зафиксировала номера строки, таким образом, никакое беспокойство о высоте.
Можно попробовать если Редактирование кнопки [button setContentVerticalAlignment:UIControlContentVerticalAlignmentTop];
:
можно попробовать этим, если Вы хотите использовать маркировку только:
Существует легкое решение для случаев, где высота маркировки не должна быть постоянной: поместите Ваш Label
в Stack View
. Обязательно добавьте ведущие и запаздывающие константы к Stack View
. Вот снимок экрана того, как сделать это в раскадровке:
У меня была подобная проблема, где было 3 маркировки. Средняя маркировка могла иметь намного более длинный текст, чем другие два, таким образом, его высота могла очень вырасти.
Как это:
я установил нижнее пространственное ограничение средней маркировки, чтобы быть> = нижняя маркировка.
, Который решил мою проблему.
необходимо разделить на подклассы 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)
}
}
Автоматическая компоновка только работает с краями/размерами контроллера, не с контроллерами content.so не хорошая идея использовать автоматическую компоновку для отображения текста метки сверху первой строки. согласно мне sizetofit является наилучшим вариантом сделать так.
Вы сделали бы это путем удаления минимальной высоты.
при необходимости в минимальной высоте к чему-то еще ниже маркировки затем, Вы использовали бы контейнерное представление, которое изменило размер на основе содержания маркировки, но использовало минимум.
У меня была та же проблема, и это - то, как я решил ее. Я просто отредактировал Базовую линию при Инспекторе Атрибута для Маркировки. Установите его для "Выравнивания Центров".
Вместо этого я изменил Нижнее Пространство, Постоянное на приоритет @250, и решил мою проблему. И моя маркировка имеет высоту, постоянную с < = постоянный
Если Вы не ограничиваетесь при наличии UILabel фиксированного размера, вместо того, чтобы выровнять текст в UILabel, просто использование ограничение ≥ на данную маркировку для изменения размера его.
Это - самое изящное решение с помощью Автоматической компоновки. Не забывайте устанавливать numberOfLines для обнуления все же.
Можно использовать UITextView вместо UILabel:
Снятие флажка "Прокрутка, включенная"
Снятие флажка, "Доступное для редактирования"
Снятие флажка, "Можно выбрать"
Выбранный цвет фона к ClearColor
Я использовал решение @Daniel Golasko и каждый раз, когда текст в UILabel был длиннее, чем UILabel мог содержать, текст начнет спускаться вместо того, чтобы остаться выровненным к вершине.
я изменил эту строку, чтобы удостовериться, что текст выровненный правильно
[super drawTextInRect:CGRectMake(0, 0, ceilf(CGRectGetWidth(self.frame)),MIN(ceilf(labelStringSize.height), self.frame.size.height))];