2014-11-13 1 views
19

Я создал образец проекта, чтобы воспроизвести это.Autolayout добавление дополнительных дополнений сверху и снизу UILabel iPhone 6/6 +, если выбраноMaxLayoutWidth установлено

У меня есть xib-файл с UILabel с фиксированным верхним, ведущим и конечным ограничениями. Я добавил ограничение minHeight и установил количество строк в 0.

Я установил для preferredMaxLayoutWidth значение Automatic (отмечено в файле xib).

В viewDidLoad, у меня это:

self.myLabel.layer.borderColor = [[UIColor redColor] CGColor]; 
self.myLabel.layer.borderWidth = 2.0f; 
self.myLabel.text = @"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."; 

И когда я запустить симулятор на iPhone 6 или 6+, я получаю это:

enter image description here

Я понятия не имею, откуда идет верхняя и нижняя прокладка, и она пропорциональна отображается количество символов в UILabel.

Есть ли какая-то волшебная установка, которую я забыл? Он отлично работает на устройствах iPhone 4.

Теперь, если я не устанавливаю предпочтительныйMaxLayoutWidth, у него нет дополнительного дополнения, но это прерывает мои многострочные линии в UILabel. Оно отсекает текст. не использовать Размер-Class

Edit:..

Так что я изменил кое-что на моем образце проекта, чтобы соответствовать ситуации на моем реальном проекте я добавил Tableview (с верхом, ведущий, нижний и конечные ограничения устанавливаются в его родительском представлении). Каждая ячейка в таблицеView имеет 4 метки. Верхняя метка имеет верхнее, ведущее и конечное ограничение для contentView ячейки, а последующие метки имеют вертикальную al ограничение метки над ним. Каждая метка имеет набор ограничений heightGreaterThan и набор widthGreaterThan.

Как выглядит это без специального набораMaxLayoutWidth (обратите внимание, как метки ограничены до 1 строки). No preferredMaxLayoutWidth

С preferredMaxLayoutWidth. Теперь UILabel показывает весь контент, но имеет дополнение сверху и снизу. With preferredMaxLayoutWidth but with top and bottom padding

Edit2: Пример проекта: https://www.dropbox.com/s/sdahx9njnsxiv98/MultiLineUILabel.zip?dl=1

+1

У меня есть точно такая же проблема, как вы. Я даже попытался взломать 'preferredMaxLayoutWidth', добавив несколько пикселей, но это число сильно зависит от того, насколько широкий экран и отличается по-разному на iPhone 6, iPhone 6+ и iPhone 5. Не говоря уже о iPad. Не уверен, что это ошибка, или если есть другие настройки/взлома, чтобы заставить ее работать. –

+0

У меня была такая же проблема, и я не использовал автоматическую компоновку. Проблема возникла только на iPhone 6, а не на iPad. Никакая комбинация настроек маски авторезистирования не имела никакого значения. В конце концов я решил проблему, выполнив очистку, перезагрузку XCode и перестройку. Странно, но он решает проблему, когда чистая сама по себе не будет. XCode 6.1.1. – JasonD

+2

Убедитесь, что предпочтительная ширина метки установлена ​​на «Автоматически», а «Явная» не отмечена на панели настроек. Это решило проблему для меня при использовании autotlayout. – AndyC

ответ

6

Так что я в конечном итоге делает было создать подкласс для метки и переопределить SetBounds: и установите preferredMaxLayoutWidth ее пределы.

- (void)setBounds:(CGRect)bounds { 
    [super setBounds:bounds]; 

    if (self.preferredMaxLayoutWidth != bounds.size.width) { 
     self.preferredMaxLayoutWidth = bounds.size.width; 
     [self setNeedsUpdateConstraints]; 
}} 

Кроме того, в подклассе UITableViewCell, я переопределить layoutSubiews

- (void)layoutSubviews { 
    [super layoutSubviews]; 

    [self.contentView layoutIfNeeded]; 

    // labelsCollection is an IBOutletCollection of my UILabel sublasses 
    for (UILabel *label in self.labelsCollection) { 
     label.preferredMaxLayoutWidth = label.bounds.size.width; 
}} 

Это работает все время. Я думаю, что причиной этого нечетного поведения является то, что UILabel изначально устанавливается на 280px (320px - padding с обеих сторон) в файле xib, но во время выполнения он меняет свою ширину, чтобы разместить большие экраны (поскольку я устанавливаю ведущую и конечную ограничений увеличивает ширину, которая меняет «preferredMaxLayoutWidth» на большее значение). По какой-то причине UILabel не обновляет свой предпочтительныйMaxLayoutWidth до большего значения и вызывает белое пространство сверху и снизу.

Это моя гипотеза.

Надеюсь, это поможет.

+0

Я знаю, что это старо, любые изменения вы также сделали это быстро, так как у него нет функции setBounds. –

+0

Nvm получил его, используя get & set и ссылаясь на supe r.bounds внутри этих get & set отлично работает. –

+1

@ MathijsSegers Можете ли вы рассказать о том, как вы это сделали? – hundley

0

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

Вместо этого вы можете попробовать использовать редактируемый UITextView с UIViewContentModeTop.

+0

Так что добавление дополнений в нижней части textView. [TextView] (http://i.imgur.com/e0ZGrWU.png) Редактирование: я должен уточнить, что высота текстаView динамически задается в коде, и в xib только 1 строка. – newDeveloper

+0

Если вы знаете размер текста раньше времени, вы можете установить ограничение по высоте и ширине на этикетке и быть уверенным, что он будет отформатировать так, как вы хотите. Также, теперь, когда я смотрю ваши правки, у вас есть линейные перерывы, установленные для Word Wrap? Не кажется, что текст обертывается так, как вы хотите. – stromdotcom

+0

Это мое последнее средство. В идеале я бы хотел, чтобы автозапуск обрабатывал его (и он отлично справляется с iPhone 4) и меньшими экранами). Изменение разрыва строки не меняет реальной проблемы (она меняет место, где она разбивает строку или показывает ...). – newDeveloper

0

Есть ли какие-либо ограничения в нижней части этикетки? Я считаю, что это позволяет растягиваться из-за приоритета обхода контента. Установите его на 1000 (обязательно). Это предотвратит его расширение за пределы его размера текста. Затем вам нужно будет добавить соответствующие ограничения для нижней части метки.

+0

Да, у меня есть нижнее ограничение по вертикали от метки к parentView (с меньшим приоритетом, чем другие), и у меня есть приоритет обхода вертикального и вертикального содержимого, установленный в 1000. – newDeveloper

+0

Хорошо. Он почти выглядит как его высота рассчитанный для 4-дюймового устройства, но затем ширина растягивается для более крупного устройства. Можете ли вы опубликовать образец проекта? –

+0

Конечно, https://www.dropbox.com/s/sdahx9njnsxiv98/MultiLineUILabel.zip?dl=1 Я отключил PreferredMaxLayoutWidth. Включите его, чтобы увидеть многострочную метку. – newDeveloper

0

Поскольку мне нужно было установить preferredMaxLayoutWidth для совместимости с iOS 7, я в итоге позвонил boundingRectWithSize, чтобы вычислить требуемую высоту ярлыка и установить постоянную константу ограничения высоты для UILabel.

CGRect labelRect = CGRectIntegral([myText boundingRectWithSize:size 
    options:options attributes:attributes context:context]); 
self.myLabelHeightConstraint.constant = labelRect.size.height; 
0

Так вот, как это реализовано в swift, В классе, расширяющем UILabel, я переопределяю границы var с помощью getter и setter, который устанавливает границы супер и возвращает его, таким образом вы можете добавить код к get и set.

Должен сказать, что я не уверен, что он все время делает магию, у меня все еще есть большие просторы.

override var bounds:CGRect { 
     get { 
      return super.bounds 
     } 
     set { 
      super.bounds = newValue 
      if (self.preferredMaxLayoutWidth != super.bounds.size.width) { 
       self.preferredMaxLayoutWidth = super.bounds.size.width; 
       self.setNeedsUpdateConstraints() 
      } 
     } 
    } 
+0

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

0

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

Я столкнулся с этой проблемой в некоторых своих проектах. Таким образом, мое решение, чтобы исправить это:

  1. В клетке я следующий метод конфигурации: - (Недействительными) configureWithSomeObject: parentViewSize: и в Tableview: cellForRowAtIndexPath: я создал ячейку, как это:

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 
    YourCell *cell; 
    
    //cell initialization 
    
    [cell configureWithSomeObject:nil parentViewSize:tableView.frame.size]; 
    
    return cell; 
    } 
    
  2. Внутри методы настройки просто установить preferredMaxLayoutWidth в соответствии с шириной родительского:

    - (void)configureWithSomeObject:(NSObject)someObject parentViewSize:(CGSize)parentViewSize { 
    // do your stuff 
    
    self.someLabel.preferredMaxLayoutWidth = parentViewSize.width; 
    } 
    

P.S. в случае, если у вас есть ведущие/конечные пробелы, вы должны вычесть его из значения parentViewSize.width.

Надеется, что это будет полезно для кого :)

0

У меня был аналогичная проблема, и только подклассы UILabel и наиважнейшая setBounds не работают для меня. При переходе через setBounds я заметил, что высота метки была 39.999999993.Так что я сделал следующие изменения, чтобы округлить до 40:

- (void)setBounds:(CGRect)bounds 
{ 
    bounds.size.height = ceilf(CGRectGetHeight(bounds)); 

    [super setBounds: bounds]; 

    if (self.preferredMaxLayoutWidth != bounds.size.width) 
    { 
     self.preferredMaxLayoutWidth = bounds.size.width; 
     [self setNeedsUpdateConstraints]; 
    } 
} 

Это установил ее для меня, не более дополнительные прокладки выше и ниже моего UILabel на больших устройствах. Мне также не нужно было устанавливать приоритет обхода контента.

1

Любой, кто изучает этот вопрос, который уже использует maxPreferredLayoutWidth (кстати, у вас нет подкласса, просто установите это в viewDidLayoutSubviews вашего VC) проверьте, что вы устанавливаете его на ширину правильного вида.

Шахта не работала, потому что у меня был:

label1.maxPreferredLayoutWidth = label1.frame.width 
label2.maxPreferredLayoutWidth = label1.frame.width 

Когда это должно было быть:

label1.maxPreferredLayoutWidth = label1.frame.width 
label2.maxPreferredLayoutWidth = label2.frame.width 

Вы видите разницу? Я не сделал в течение 3 часов лол

+1

Для тех, кто не видит ...это 'label1' vs' label2' после символов '=' во вторых строках – BallpointBen

1

используя этот класс установил ее для меня

import UIKit 

class CustomLabel: 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) 
     } 
    } 

} 
Смежные вопросы