62
задан 23 May 2017 в 15:26

16 ответов

Редактирование

В моем исходном ответе я использовал стиль абзаца маркировки. Оказывается, что для многострочных маркировок это на самом деле препятствует тому, чтобы маркировка была мультилинией. В результате я удалил его из вычисления. Посмотрите больше об этом в , Github

Для тех из Вас более довольный использованием Открытого исходного кода определенно смотрит TTTAttributedLabel, где можно установить выравнивание текста маркировки на TTTAttributedLabelVerticalAlignmentTop

<час>

, прием должен разделить на подклассы UILabel и переопределение drawTextInRect. Затем осуществите это, текст оттянут в источнике границ маркировки.

Вот наивная реализация, которую можно использовать прямо сейчас:

Objective C Swift

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

Swift 3

  @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, можно добавить эту маркировку к раскадровке и часам, это идет, это - то, на что это похоже для меня

enter image description here

131
ответ дан 31 October 2019 в 13:06

использование этот мой класс, можно изменить текст 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)
        }
    }

}
0
ответ дан 31 October 2019 в 13:06

Вот улучшение на Быстрых 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
    }
}
0
ответ дан 31 October 2019 в 13:06
  @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()
      }
    }
  }
0
ответ дан 31 October 2019 в 13:06

Для меня я не установил ограничение высоты, текст всегда растет от вершины маркировки. Ограничения для этой маркировки являются вершиной, оставленной, право. Между прочим, моя маркировка зафиксировала номера строки, таким образом, никакое беспокойство о высоте.

0
ответ дан 31 October 2019 в 13:06

Можно попробовать если Редактирование кнопки [button setContentVerticalAlignment:UIControlContentVerticalAlignmentTop];

:

можно попробовать этим, если Вы хотите использовать маркировку только:

https://stackoverflow.com/a/11278660/1223897

0
ответ дан 31 October 2019 в 13:06

Существует легкое решение для случаев, где высота маркировки не должна быть постоянной: поместите Ваш Label в Stack View. Обязательно добавьте ведущие и запаздывающие константы к Stack View. Вот снимок экрана того, как сделать это в раскадровке:

enter image description here

1
ответ дан 31 October 2019 в 13:06

У меня была подобная проблема, где было 3 маркировки. Средняя маркировка могла иметь намного более длинный текст, чем другие два, таким образом, его высота могла очень вырасти.

Как это:

enter image description here

я установил нижнее пространственное ограничение средней маркировки, чтобы быть> = нижняя маркировка.

enter image description here

, Который решил мою проблему.

1
ответ дан 31 October 2019 в 13:06

Быстро 4

необходимо разделить на подклассы 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)
    }
}
1
ответ дан 31 October 2019 в 13:06

Автоматическая компоновка только работает с краями/размерами контроллера, не с контроллерами content.so не хорошая идея использовать автоматическую компоновку для отображения текста метки сверху первой строки. согласно мне sizetofit является наилучшим вариантом сделать так.

1
ответ дан 31 October 2019 в 13:06

Вы сделали бы это путем удаления минимальной высоты.

при необходимости в минимальной высоте к чему-то еще ниже маркировки затем, Вы использовали бы контейнерное представление, которое изменило размер на основе содержания маркировки, но использовало минимум.

4
ответ дан 31 October 2019 в 13:06

У меня была та же проблема, и это - то, как я решил ее. Я просто отредактировал Базовую линию при Инспекторе Атрибута для Маркировки. Установите его для "Выравнивания Центров".

Setting baseline to Align Centers

8
ответ дан 31 October 2019 в 13:06

Вместо этого я изменил Нижнее Пространство, Постоянное на приоритет @250, и решил мою проблему. И моя маркировка имеет высоту, постоянную с < = постоянный

7
ответ дан 31 October 2019 в 13:06

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

enter image description here

Это - самое изящное решение с помощью Автоматической компоновки. Не забывайте устанавливать numberOfLines для обнуления все же.

39
ответ дан 31 October 2019 в 13:06

Можно использовать UITextView вместо UILabel:
Снятие флажка "Прокрутка, включенная"
Снятие флажка, "Доступное для редактирования"
Снятие флажка, "Можно выбрать"
Выбранный цвет фона к ClearColor

33
ответ дан 31 October 2019 в 13:06

Я использовал решение @Daniel Golasko и каждый раз, когда текст в UILabel был длиннее, чем UILabel мог содержать, текст начнет спускаться вместо того, чтобы остаться выровненным к вершине.

я изменил эту строку, чтобы удостовериться, что текст выровненный правильно

    [super drawTextInRect:CGRectMake(0, 0, ceilf(CGRectGetWidth(self.frame)),MIN(ceilf(labelStringSize.height), self.frame.size.height))];
1
ответ дан 31 October 2019 в 13:06

Другие вопросы по тегам:

Похожие вопросы: