Как я могу сделать текст макета UITextView таким же, как UILabel?

У меня есть UILabel, который мне нужно преобразовать в UITextView по причинам. Когда я это делаю, текст не устанавливается одинаково, несмотря на то, что используется тот же (пользовательский) шрифт.

Я обнаружил, что если я устанавливаю:

textView.textContainer.lineFragmentPadding = 0;
textView.textContainerInset = UIEdgeInsetsZero;

Этот текст очень близок, но если я наложу UITextView поверх вершины UILabel, я вижу, что позиционирование текста больше разделяется с каждой новой строкой.

Screen shot showing text drift.

UILabel зеленый, UITextView черный. Это использует NSParagraphStyle для установки минимальной и максимальной высоты строки до 15.

Я играл с настройкой стиля абзаца и минимальной высоты строки, но я точно не смог его сопоставить. Я не принтер, поэтому я не обязательно понимаю все термины, связанные с термином в документации для NSLayoutManager и NSTextContainer, и все это.

Мне нужно только поддерживать iOS 7 и выше.

Я не собираюсь переключаться на какой-то сумасшедший пользовательский виджет на основе CoreText или использовать какую-то случайную стороннюю библиотеку. Я в порядке, если нужно. Но похоже, что должна быть некоторая комбинация случайных свойств, чтобы сделать их макет одинаковыми.

Ответы

Ответ 1

Я принял решение для межстрочного интервала, найденного по этой ссылке, и применил его к вашей проблеме. Мне удалось сделать это невероятно близко, настроив свойство lineSpacing. Я протестировал с HelveticaNeue размером 13 и сумел заставить его выстраиваться в линию, как показано на снимке экрана ниже.

textView.textContainer.lineFragmentPadding = 0;
textView.textContainerInset = UIEdgeInsetsZero;

NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];

paragraphStyle.lineSpacing = -0.38;

NSDictionary *attrsDictionary =
@{ NSFontAttributeName: [UIFont fontWithName:@"HelveticaNeue" size:13.0f],
 NSParagraphStyleAttributeName: paragraphStyle};

textView.attributedText = [[NSAttributedString alloc] initWithString:textView.text attributes:attrsDictionary];

Screen Shot

Ответ 2

Я смог успешно "выдавать себя за" нередактируемую многострочную UILabel (как это происходит в подклассе UITableViewCell) с эквивалентным редактируемым многострочным UITextView, используя следующее:

_textView = UITextView.new;
_textView.font = _label.font;
_textView.textColor = _label.textColor;
_textView.textAlignment = _label.textAlignment;
_textView.backgroundColor = UIColor.clearColor;
_textView.textContainer.lineFragmentPadding = 0;
_textView.textContainerInset = UIEdgeInsetsZero;

и чтобы он хорошо себя вел при выполнении реальных изменений, добавьте следующее в свой UITextViewDelegate:

- (void)textViewDidChange:(UITextView *)textView
{
    ...
    [textView scrollRangeToVisible:NSMakeRange(textView.text.length, 0)];
    [textView scrollRectToVisible:[textView caretRectForPosition:textView.endOfDocument] animated:NO];
}