UITableViewCell с autolayout левое поле отличается на iPhone и iPad
Я использую сгруппированы UITableView
со статическими ячейками для экрана/сцены параметров. Все сделано в Xcode 6.1 / iOS 8.1.x / раскадровка с использованием автозапуска. Внутри групп таблиц есть смешанные типы ячеек и есть два типа, которые вызывают у меня проблемы:
- ячейки с пользовательским стилем и
- ячейки со стилем "правильная деталь"
в ячейке #1 я могу установить ограничение для левого поля между меткой и ведущим контейнером. На ячейка #2 я не могу установить какие-либо ограничения в Interface Builder, насколько я знаю. Я установил левое поле на метке в ячейке №1, чтобы оно совпадало с меткой в ячейке № 2. Все выглядит нормально на iPhone, но если я покажу ту же таблицу на iPad, где размер контейнера представления таблицы составляет половину размера экрана, ячейка #2 получает больше маржи (динамически?) в то время как ячейка № 1 поддерживает абсолютную маржу, которую я установил в ограничениях. Я также попытался изменить левое поле в ячейке №1 с атрибутом "относительно маржи", но безрезультатно.
iPhone:
iPad (с шириной tableview = 1/2 размера экрана)
Итак, вопрос: Как установить ограничения для метки в ячейке #1, чтобы она выравнивалась как ячейка #2.
вот также ссылка на пример проекта Xcode 6.1, демонстрирующий проблему. Работать на iPhone и iPad, чтобы увидеть разница:
https://dl.dropboxusercontent.com/u/5252156/Code/tableViewTest.zip
этот вопрос может быть связано с макет статической ячейки таблицы для iPhone и iPad, но это может также отличаться для iOS 8, так как теперь все должно быть адаптивным. Вот почему я решил разместить этот вопрос.
5 ответов:
как это исправить
после борьбы с командой apple bug reporting со многими образцами проектов и скриншотов и рассечения что ответ, я обнаружил, что решение для того, чтобы ваши ячейки пользовательского стиля вели себя последовательно относительно их полей и были такими же, как uitableviewcells по умолчанию, вам нужно сделать следующее (в основном на основе Бекки!--8-->, я выделил, что отличается, и что заставило его работать на меня) :
- выберите просмотр содержимого в IB
- перейти к инспектору размера
в разделе поля макета, проверьте сохранить поля супервизора (не нажимайте на знак плюс)
(и вот ключ) сделайте то же самое для самой клетки (родитель представления содержимого, если вы Уилл)
настройка ограничений следующим образом: метка.Ведущий = Супервизор.Ведущий запас (с константой 0)
теперь все ваши ячейки будут иметь свою метку, соответствующую ячейкам по умолчанию! Это работает для меня в Xcode 7 и выше, и он включает в себя исправление, упомянутое в потоке, на который я ссылался. МБ и симулятор теперь должны отображаться правильно ценник.
вы также можете сделать это программно, например, в классе контроллера вида:
cell.preservesSuperviewLayoutMargins = true cell.contentView.preservesSuperviewLayoutMargins = true
или вы можете настроить его, вызвав UIAppearance один раз при запуске (я знаю только Swift, извините) :
UITableViewCell.appearance().preservesSuperviewLayoutMargins = true UITableViewCell.appearance().contentView.preservesSuperviewLayoutMargins = true
как и почему он работает
как Итан любезно указал, что собственная документация Apple по UIView описывает
preservesSuperviewLayoutMargins
следующим образом :когда значение этого свойства
true
, поля супервизора также учитываются при размещении контента. Это поле влияет на макеты, где расстояние между краем вида и его супервизором меньше, чем соответствующее поле. Например, у вас может быть представление содержимого, фрейм которого точно соответствует границам его супервизора. Когда любое из полей супервизора находится внутри области, представленной представлением содержимого и его собственными полями, UIKit настраивает макет представления содержимого с учетом полей супервизора. Размер корректировки-это наименьшая сумма, необходимая для обеспечения того, чтобы содержимое также находилось внутри полей супервизора.поэтому, если вы хотите, чтобы содержимое ячейки в соответствии с TableView поля (это прапрадедушка, если хотите), вам нужно иметь два родителя вашего контента, представление контента и саму ячейку таблицы, сохранить поля своих собственных супервизор.
почему это не поведение по умолчанию удивляет меня: я чувствую, что большинство разработчиков, которые не хотят настраивать все, ожидали бы этого "наследования" по умолчанию.
я столкнулся с той же проблемой, что и вы, и придумал решение.
во-первых, немного фона: начиная с iOS 8, ячейки представления таблицы по умолчанию уважают ячейку
layoutMargins
для адаптации к различным чертам (ака экраны ака устройств). Например, поля макета на всех iPhones (кроме iPhone 6 Plus, когда они показаны на листе формы) являются{8, 16, 8, 16}
. На iPad они{8, 20, 8, 20}
. Итак, теперь мы знаем, что есть разница в 4 пикселя, которая, скорее всего, не соответствует вашей пользовательской ячейке представления таблицы уважать.ваш подкласс ячейки табличного представления должен адаптировать ограничение левого поля при изменении layoutMargins.
вот соответствующий фрагмент кода:
- (void)layoutMarginsDidChange { [super layoutMarginsDidChange]; self.leftLayoutMarginConstraint.constant = self.layoutMargins.left; self.rightLayoutMarginConstraint.constant = self.layoutMargins.right; }
адаптация к полям макета в коде позволяет вам всегда получать правильное заполнение для вашей метки заголовка.
вы также можете взглянуть на один из моих подклассов UITableViewCell, которые уже уважают layoutMargins: https://github.com/bhr/BHRExtensions/blob/master/BHRExtensions/Utilities/BHRTitleAndValueTableCell.m
Ура
прочитав существующие ответы и не найдя очевидного программного решения, я еще немного покопался и теперь у меня есть хороший ответ для всех, кто сталкивается с этой проблемой.
во-первых, это не обязательно устанавливать
preservesSuperviewLayoutMargins
к представлению ячейки или представлению содержимого как другоеответы подразумевают. В то время как значение по умолчанию:false
об этомtrue
не было никакого заметного эффекта, который я мог видеть.ключ для этого на самом деле работа-это
layoutMarginsGuide
собственности наUIView
. Используя это значение, мы можем просто легко закрепитьleadingAnchor
любого подвида кleadingAnchor
руководства. Вот как это выглядит в коде (и вполне может быть то, что IB делает за кулисами, как в Джонас).на
UITableViewCell
подкласс, вы бы сделали что-то вроде этого:override func updateConstraints() { let margins = contentView.layoutMarginsGuide let leading = margins.leadingAnchor subview1.leadingAnchor.constraintEqualToAnchor(leading).active = true subview2.leadingAnchor.constraintEqualToAnchor(leading).active = true super.updateConstraints() }
Swift 4.1 update
override func updateConstraints() { let margins = contentView.layoutMarginsGuide let leading = margins.leadingAnchor subview1.leadingAnchor.constraint(equalTo: leading).isActive = true subview2.leadingAnchor.constraint(equalTo: leading).isActive = true super.updateConstraints() }
вот и все! Если вы разрабатываете для iOS версии до iOS 9 вам нужно будет заменить якоря макета и использовать
layoutMargins
вместо вставкой.
Примечание: я написал библиотеку, чтобы сделать якорь закрепления немного красивее, если вы предпочитаете более чистый синтаксис. Это называется SuperLayout и доступно на Cocoapods. В верхней части исходного файла, импорт
SuperLayout
:import SuperLayout
а затем в вашем блоке макета, используйте
~~
,≤≤
и≥≥
для закрепления ограничений:override func updateConstraints() { let margins = contentView.layoutMarginsGuide subview1.leadingAnchor ~~ margins.leadingAnchor subview2.leadingAnchor ~~ margins.leadingAnchor super.updateConstraints() }
Я смог получить ячейки с пользовательскими стилями, выровненными со стандартными ячейками, выполнив следующие действия:
- в структуре документа выберите "вид содержимого" для ячейки с пользовательские стили.
- перейдите к инспектору размеров.
- в раскрывающемся списке " поля макета "нажмите маленький символ плюс рядом с" сохранить поля супервизора."
- выберите класс размера iPad ,который является " обычная ширина x обычная высота."
- Регистрация флажок рядом с "сохранить поля супервизора."
- разрешите любые предупреждения автоматической компоновки, обновив кадры.
Это сработало для меня в Xcode 7; я надеюсь, что он будет работать и в Xcode 6.
У меня была эта проблема при тестировании на iPad Air, OS 10.1.1. Заголовки таблицы были изрезаны гораздо дальше, чем должны были, и это было даже хуже в альбомной ориентации. Но они были в порядке на iPhone до OS 11.
удивительным решением была следующая строка кода, сразу после создания таблицы (Извините, я работаю только на C#, но легко разработать эквиваленты Obj-C и Swift):
myTableView.SeparatorInset = myTableView.SeparatorInset;
затем все было отступом, как и должно быть!