Как вы используете Auto Layout внутри UITableViewCell
s в табличном представлении, чтобы содержимое и подпредставления каждой ячейки определяли высоту строки (само / автоматически), сохраняя при этом плавную прокрутку?
ios
uitableview
autolayout
nsautolayout
row-height
smileyborg
источник
источник
contentSize
и какpreferredMaxLayoutWidth
работать. Смотрите здесь . Тем не менее, если вы правильно настроите свои ограничения, то вам это не нужноpreferredMaxLayoutWidth
и фактически может привести к неожиданным результатам.Ответы:
TL; DR: не любишь читать? Перейдите прямо к образцам проектов на GitHub:
Концептуальное описание
Первые 2 шага ниже применимы независимо от того, для каких версий iOS вы разрабатываете.
1. Установите и добавьте ограничения
В своем
UITableViewCell
подклассе добавьте ограничения, чтобы у подвидов ячейки были прикреплены края к краям содержимого содержимого ячейки (наиболее важно к верхним и нижним кромкам). ПРИМЕЧАНИЕ: не прикрепляйте подпредставления к самой ячейке; только к клеткеcontentView
! Позвольте внутреннему размеру содержимого этих подпредставлений управлять высотой представления содержимого ячейки табличного представления, следя за тем, чтобы сопротивление сжатию содержимого и ограничения объятия содержимого в вертикальном измерении для каждого подпредставления не переопределялись добавленными вами ограничениями более высокого приоритета. ( Да? Нажмите здесь. )Помните, что идея состоит в том, чтобы подключить подпредставления ячейки вертикально к представлению содержимого ячейки, чтобы они могли «оказывать давление» и расширять представление содержимого в соответствии с ними. Используя примерную ячейку с несколькими подпредставлениями, вот наглядная иллюстрация того, как должны выглядеть некоторые (не все!) Ваши ограничения:
Вы можете себе представить, что по мере того, как в метку многострочного тела в приведенной выше ячейке добавляется больше текста, он должен будет расти вертикально, чтобы соответствовать тексту, что будет эффективно увеличивать высоту ячейки. (Конечно, для правильной работы необходимо правильно настроить ограничения!)
Правильное определение ограничений - определенно самая трудная и важная часть получения динамических высот ячеек при работе с Auto Layout. Если вы допустите здесь ошибку, это может помешать работе всего остального - так что не торопитесь! Я рекомендую установить ваши ограничения в коде, потому что вы точно знаете, какие ограничения добавляются и куда легче отладить, когда что-то пойдет не так. Добавление ограничений в код может быть таким же простым и значительно более мощным, чем Interface Builder с использованием якорей компоновки или одного из фантастических API с открытым исходным кодом, доступных на GitHub.
updateConstraints
метода вашего подкласса UITableViewCell. Обратите внимание, что этоupdateConstraints
может быть вызвано более одного раза, поэтому, чтобы избежать добавления одних и тех же ограничений более одного раза, убедитесь, что оберните свой код добавления ограниченийupdateConstraints
в проверку для логического свойства, такого какdidSetupConstraints
(которое вы установили в YES после запуска вашего ограничения добавив код один раз). С другой стороны, если у вас есть код, который обновляет существующие ограничения (например, корректируетconstant
свойство для некоторых ограничений), поместите его,updateConstraints
но вне проверки,didSetupConstraints
чтобы он мог запускаться каждый раз, когда вызывается метод.2. Определите уникальные идентификаторы повторного использования ячеек таблицы
Для каждого уникального набора ограничений в ячейке используйте уникальный идентификатор повторного использования ячейки. Другими словами, если ваши ячейки имеют более одного уникального макета, каждый уникальный макет должен получить свой собственный идентификатор повторного использования. (Хороший совет, что вам нужно использовать новый идентификатор повторного использования, это когда ваш вариант ячейки имеет разное количество подпредставлений, или подпредставления расположены по-разному.)
Например, если вы отображали сообщение электронной почты в каждой ячейке, у вас может быть 4 уникальных макета: сообщения только с темой, сообщения с темой и телом, сообщения с темой и вложением фотографии и сообщения с темой, тело и фото вложения. Каждый макет имеет совершенно разные ограничения, необходимые для его достижения, поэтому после инициализации ячейки и добавления ограничений для одного из этих типов ячеек ячейка должна получить уникальный идентификатор повторного использования, специфичный для этого типа ячейки. Это означает, что когда вы удаляете ячейку из очереди для повторного использования, ограничения уже добавлены и готовы перейти на этот тип ячейки.
Обратите внимание, что из-за различий в собственном размере контента ячейки с одинаковыми ограничениями (типом) могут по-прежнему иметь разную высоту! Не путайте принципиально разные макеты (разные ограничения) с разными вычисленными рамками вида (решенными из одинаковых ограничений) из-за разного размера контента.
Для iOS 8 - Ячейки с самоконтролем
3. Включить оценку высоты строки
В iOS 8 компания Apple усвоила большую часть работы, которую вы должны были выполнить ранее до iOS 8. Чтобы позволить механизму ячеек с самоопределением размера работать, вы должны сначала установить для
rowHeight
свойства в табличном представлении константуUITableViewAutomaticDimension
, Затем вам просто нужно включить оценку высоты строки, установив дляestimatedRowHeight
свойства табличного представления ненулевое значение, например:Это обеспечивает временное представление / заполнитель табличного представления для высот строк ячеек, которые еще не отображены на экране. Затем, когда эти ячейки будут прокручиваться на экране, будет вычислена фактическая высота строки. Чтобы определить фактическую высоту для каждой строки, табличное представление автоматически запрашивает каждую ячейку, какую высоту она
contentView
должна основывать на известной фиксированной ширине представления содержимого (которая основана на ширине табличного представления, за вычетом любых дополнительных вещей, таких как индекс раздела). или вспомогательное представление) и ограничения автоматического размещения, добавленные в представление содержимого и подпредставления ячейки. Как только эта фактическая высота ячейки была определена, старая оценочная высота для строки обновляется с новой фактической высотой (и любые корректировки для contentSize / contentOffset табличного представления выполняются по мере необходимости для вас).Вообще говоря, предоставленная вами оценка не обязательно должна быть очень точной - она используется только для правильного определения размера индикатора прокрутки в табличном представлении, и табличное представление хорошо настраивает индикатор прокрутки для неверных оценок, поскольку вы прокрутка клеток на экране. Вы должны установить
estimatedRowHeight
свойство в табличном представлении (viewDidLoad
или аналогичное) на постоянное значение, которое является «средней» высотой строки. Только в том случае, если ваши высоты строк имеют экстремальную изменчивость (например, отличаются на порядок) и вы замечаете, что индикатор прокрутки «прыгает» во время прокрутки, вам следует потрудитьсяtableView:estimatedHeightForRowAtIndexPath:
выполнить минимальные вычисления, необходимые для получения более точной оценки для каждой строки.Для поддержки iOS 7 (автоматическое определение размеров ячеек)
3. Выполните макет Pass & Get The Cell Height
Во-первых, создайте экземпляр закадрового экземпляра ячейки табличного представления, по одному экземпляру для каждого идентификатора повторного использования , который используется строго для расчета высоты. (Вне экрана означает, что ссылка на ячейку хранится в свойстве / ivar на контроллере представления и никогда не возвращается из
tableView:cellForRowAtIndexPath:
таблицы для фактического отображения на экране.) Затем ячейка должна быть настроена с точным содержимым (например, текстом, изображениями и т. Д.) что он будет иметь место, если он будет отображаться в табличном представлении.Затем заставить ячейку сразу макет его подвидов, а затем использовать
systemLayoutSizeFittingSize:
метод наUITableViewCell
«s ,contentView
чтобы выяснить , что требуемая высота ячейки. ИспользуйтеUILayoutFittingCompressedSize
для получения наименьшего размера, необходимого для размещения всего содержимого ячейки. Затем высоту можно вернуть изtableView:heightForRowAtIndexPath:
метода делегата.4. Используйте Расчетные высоты строк
Если в вашем табличном представлении содержится более пары десятков строк, вы обнаружите, что выполнение решения ограничений Auto Layout может быстро увязнуть с основным потоком при первой загрузке табличного представления, как это
tableView:heightForRowAtIndexPath:
вызывается в каждой строке при первой загрузке ( для того, чтобы рассчитать размер индикатора прокрутки).Начиная с iOS 7, вы можете (и обязательно должны) использовать
estimatedRowHeight
свойство в табличном представлении. Это обеспечивает временное представление / заполнитель табличного представления для высот строк ячеек, которые еще не отображены на экране. Затем, когда эти ячейки будут прокручиваться на экране, будет вычислена фактическая высота строки (путем вызоваtableView:heightForRowAtIndexPath:
), а оценочная высота будет обновлена с фактической.Вообще говоря, предоставленная вами оценка не обязательно должна быть очень точной - она используется только для правильного определения размера индикатора прокрутки в табличном представлении, и табличное представление хорошо настраивает индикатор прокрутки для неверных оценок, поскольку вы прокрутка клеток на экране. Вы должны установить
estimatedRowHeight
свойство в табличном представлении (viewDidLoad
или аналогичное) на постоянное значение, которое является «средней» высотой строки. Только в том случае, если ваши высоты строк имеют экстремальную изменчивость (например, отличаются на порядок) и вы замечаете, что индикатор прокрутки «прыгает» во время прокрутки, вам следует потрудитьсяtableView:estimatedHeightForRowAtIndexPath:
выполнить минимальные вычисления, необходимые для получения более точной оценки для каждой строки.5. (Если необходимо) Добавьте кеширование высоты строки
Если вы выполнили все вышеперечисленное и по-прежнему обнаруживаете, что производительность при решении ограничений является недопустимо низкой
tableView:heightForRowAtIndexPath:
, вам, к сожалению, потребуется реализовать некоторое кэширование для высоты ячеек. (Это подход, предложенный инженерами Apple.) Общая идея состоит в том, чтобы позволить механизму Autolayout в первый раз решить ограничения, затем кэшировать вычисленную высоту для этой ячейки и использовать кэшированное значение для всех будущих запросов на высоту этой ячейки. Трюк, конечно, состоит в том, чтобы убедиться, что вы очищаете кэшированную высоту для ячейки, когда происходит что-то, что может привести к изменению высоты ячейки - в первую очередь, это происходит, когда изменяется содержимое этой ячейки или когда происходят другие важные события (например, пользователь настраивает ползунок размера текста динамического типа).Типовой код iOS 7 (с множеством сочных комментариев)
Примеры проектов
Эти проекты являются полностью рабочими примерами табличных представлений с переменной высотой строк из-за ячеек табличного представления, содержащих динамическое содержимое в UILabels.
Ксамарин (C # /. NET)
Если вы используете Xamarin, посмотрите этот пример проекта, составленный @KentBoogaart .
источник
heightForRowAtIndexPath
, сохранив ячейку и вернув ее в следующий разcellForRowAtIndexPath
.iOS8
реализация еще рекомендуетсяiOS9
иiOS10
, или там новые подходы , так как этот ответ был опубликован?Для iOS 8 и выше это действительно просто:
или
Но для iOS 7 ключ вычислить высоту после автоматического размещения:
Важный
Если несколько строк меток, не забудьте установить
numberOfLines
в0
.Не забывай
label.preferredMaxLayoutWidth = CGRectGetWidth(tableView.bounds)
Полный пример кода здесь .
источник
Быстрый пример переменной высоты UITableViewCell
Обновлено для Swift 3
Быстрый ответ Уильяма Ху хорош, но он помогает мне сделать несколько простых, но подробных шагов, когда я впервые учусь что-то делать. Приведенный ниже пример - мой тестовый проект, в котором я учусь создавать
UITableView
переменные ячейки. Я основал его на этом базовом примере UITableView для Swift .Готовый проект должен выглядеть так:
Создать новый проект
Это может быть только приложение с одним представлением.
Добавьте код
Добавьте новый файл Swift в свой проект. Назовите это MyCustomCell. Этот класс будет содержать выходы для представлений, которые вы добавляете в свою ячейку в раскадровке. В этом базовом примере у нас будет только одна метка в каждой ячейке.
Мы подключим эту розетку позже.
Откройте ViewController.swift и убедитесь, что у вас есть следующее содержимое:
Важная заметка:
Перечисленные ниже две строки кода (вместе с автоматической разметкой) делают возможной переменную высоту ячейки:
Настройте раскадровку
Добавьте табличное представление к вашему контроллеру представления и используйте автоматическое расположение, чтобы прикрепить его к четырем сторонам. Затем перетащите ячейку табличного представления в табличное представление. На ячейку Prototype перетащите метку. Используйте автоматическое расположение, чтобы прикрепить метку к четырем краям представления содержимого ячейки табличного представления.
Важная заметка:
Другие настройки IB
Пользовательское имя класса и идентификатор
Выберите ячейку табличного представления и задайте для настраиваемого класса значение
MyCustomCell
(имя класса в добавленном нами файле Swift). Также установите Идентификатор какcell
(та же строка, которую мы использовали дляcellReuseIdentifier
в коде выше.Ноль линий для метки
Установите количество строк
0
в вашей метке. Это означает многострочность и позволяет метке изменять размер в зависимости от содержимого.Подключить розетки
tableView
переменную вViewController
коде.myCellLabel
переменной вMyCustomCell
классе.Законченный
Вы должны быть в состоянии запустить ваш проект сейчас и получить ячейки с переменной высотой.
Ноты
Если вы не закрепляете передний и задний (левый и правый) края, вам также может понадобиться установить метки
preferredMaxLayoutWidth
так, чтобы они знали, когда переносить строки. Например, если вы добавили ограничение «Центр по горизонтали» к метке в вышеприведенном проекте, а не прикрепили переднюю и заднюю кромки, вам нужно добавить эту строку вtableView:cellForRowAtIndexPath
метод:Смотрите также
источник
preferredMaxLayoutWidth
противопоставить клеткиcontentSize
? Таким образом, если у вас есть accessoryView или он был отсканирован для редактирования, то это все равно будет принято во внимание?Я обернул решение @ smileyborg для iOS7 в категорию
Я решил обернуть это умное решение @smileyborg в
UICollectionViewCell+AutoLayoutDynamicHeightCalculation
категорию.Категория также устраняет проблемы, описанные в ответе @ wildmonkey (загрузка ячейки из пера и
systemLayoutSizeFittingSize:
возвратCGRectZero
)Он не учитывает никакого кеширования, но соответствует моим потребностям прямо сейчас. Не стесняйтесь копировать, вставлять и взламывать его.
UICollectionViewCell + AutoLayoutDynamicHeightCalculation.h
UICollectionViewCell + AutoLayoutDynamicHeightCalculation.m
Пример использования:
К счастью, нам не придется заниматься этим джазом в iOS8, но пока он есть!
источник
[YourCell new]
и использовать его как пустышку. Пока код создания кода ограничения запускается в вашем экземпляре, и вы запускаете передачу макета программным способом, вы должны быть в порядке.UICollectionViews
также.Вот мое решение:
Вы должны рассказать , прежде чем он загружает вид. В противном случае он не сможет вести себя так, как ожидалось.
TableView
estimatedHeight
Objective-C
Обновление до Swift 4.2
источник
estimatedRowHeight
меняется строка за строкой? я должен преувеличивать или недооценивать? использовать минимальную или максимальную высоту, в которой я используюtableView
?estimatedRowHeight
, это в основном влияет на размер полосы прокрутки, а не на высоту реальных ячеек. Будьте жирны на выбранной вами высоте: это повлияет на анимацию вставки / удаления.Решение, предложенное @smileyborg, практически идеально. Если у вас есть пользовательская ячейка, и вы хотите одну или несколько
UILabel
с динамическими высотами, то метод systemLayoutSizeFittingSize в сочетании с включенным AutoLayout возвращает a,CGSizeZero
если вы не переместите все ограничения вашей ячейки из ячейки в ее contentView (как предложено здесь @TomSwift. Как изменить размер superview для подходит для всех подпредставлений с autolayout? ).Для этого вам нужно вставить следующий код в вашу пользовательскую реализацию UITableViewCell (спасибо @Adrian).
Смешивание ответа @smileyborg с этим должно работать.
источник
systemLayoutSizeFittingSize
должен вызываться на contentView, а не на ячейкуДостаточно важный вопрос, с которым я столкнулся, чтобы опубликовать ответ.
Ответ @ smileyborg в основном правильный. Однако, если у вас есть код в
layoutSubviews
методе вашего пользовательского класса ячеек, например, для установкиpreferredMaxLayoutWidth
, то он не будет выполняться с этим кодом:Это смутило меня на некоторое время. Тогда я понял, что это потому, что они только вызывают layoutSubviews на
contentView
, а не саму ячейку.Мой рабочий код выглядит так:
Обратите внимание, что если вы создаете новую ячейку, я уверен, что вам не нужно звонить
setNeedsLayout
как она уже должна быть установлена. В случаях, когда вы сохраняете ссылку на ячейку, вам, вероятно, следует вызвать ее. В любом случае это ничего не должно повредить.Еще один совет, если вы используете подклассы ячеек, где вы устанавливаете такие вещи, как
preferredMaxLayoutWidth
. Как упоминает @smileyborg, «ваша ячейка табличного представления еще не имеет своей ширины, привязанной к ширине табличного представления». Это верно, и проблема, если вы выполняете свою работу в своем подклассе, а не в контроллере представления. Однако вы можете просто установить рамку ячейки в этой точке, используя ширину таблицы:Например, в расчете на высоту:
(Я случайно кеширую эту ячейку для повторного использования, но это не имеет значения).
источник
В случае, если у людей все еще есть проблемы с этим. Я написал краткое сообщение в блоге об использовании Autolayout с UITableViews, использующим Autolayout для динамических высот ячеек, а также компонент с открытым исходным кодом, чтобы помочь сделать это более абстрактным и простым в реализации. https://github.com/Raizlabs/RZCellSizeManager
источник
Пока ваш макет в вашей камере хорошо.
Обновление: вы должны использовать динамическое изменение размеров, представленное в iOS 8.
источник
tableView:cellForRowAtIndexPath:
вtableView:heightForRowAtIndexPath:
сейчас?systemLayoutSizeFittingSize:
вtableView:cellForRowAtIndexPath:
и кэшировать результат тогда , а затем использовать его вtableView:heightForRowAtIndexPath:
это работает хорошо, пока ограничения настроены правильно, конечно!(для Xcode 8.x / Xcode 9.x читайте внизу)
Остерегайтесь следующей проблемы в Xcode 7.x, которая может быть источником путаницы:
Интерфейсный Разработчик не обрабатывает автоматическую настройку размера ячейки должным образом. Даже если ваши ограничения абсолютно действительны, IB все равно будет жаловаться и давать вам запутанные предложения и ошибки. Причина в том, что IB не желает изменять высоту строки в соответствии с вашими ограничениями (чтобы ячейка соответствовала вашему контенту). Вместо этого он сохраняет фиксированную высоту строки и начинает предлагать вам изменить ограничения, которые вы должны игнорировать .
Например, представьте, что вы все настроили нормально, без предупреждений, без ошибок, все работает.
Теперь, если вы измените размер шрифта (в этом примере я изменяю размер шрифта метки описания с 17.0 до 18.0).
Поскольку размер шрифта увеличился, метка теперь хочет занимать 3 строки (до этого она занимала 2 строки).
Если Интерфейсный Разработчик работал как ожидалось, он изменил бы высоту ячейки, чтобы приспособить новую высоту метки. Однако на самом деле происходит то, что IB отображает красный значок ошибки автоматического макета и предлагает вам изменить приоритеты объятия / сжатия.
Вы должны игнорировать эти предупреждения. Вместо этого * можно вручную изменить высоту строки (выберите «Ячейка»> «Инспектор размера»> «Высота строки»).
Я менял эту высоту по одному клику за раз (используя шаговый регулятор вверх / вниз), пока ошибки красной стрелки не исчезли! (вы получите желтые предупреждения, после чего просто продолжайте и «обновляйте фреймы», все должно работать).
* Обратите внимание, что на самом деле вам не нужно устранять эти красные ошибки или желтые предупреждения в Интерфейсном Разработчике - во время выполнения все будет работать правильно (даже если IB показывает ошибки / предупреждения). Просто убедитесь, что во время выполнения в журнале консоли вы не получаете никаких ошибок AutoLayout.
На самом деле, пытаться всегда обновлять высоту строки в IB очень раздражает, а иногда и почти невозможно (из-за дробных значений).
Чтобы избежать раздражающих предупреждений / ошибок IB, вы можете выбрать соответствующие представления, а
Size Inspector
для свойстваAmbiguity
выбратьVerify Position Only
Xcode 8.x / Xcode 9.x, кажется, (иногда) работает не так, как Xcode 7.x, но все же неправильно. Например, даже когда
compression resistance priority
/hugging priority
установлены на обязательные (1000), Interface Builder может растянуть или обрезать метку, чтобы она соответствовала ячейке (вместо изменения высоты ячейки, чтобы она соответствовала метке). И в таком случае он может даже не показывать никаких предупреждений или ошибок AutoLayout. Или иногда он делает именно то, что сделал Xcode 7.x, описанный выше.источник
Чтобы установить автоматическое измерение для высоты строки и предполагаемой высоты строки, выполните следующие шаги, чтобы автоматическое измерение было эффективным для макета высоты ячейки / строки.
UITableViewAutomaticDimension
rowHeight & оценкаRowHeightheightForRowAt
и верните ему значениеUITableViewAutomaticDimension
)-
Цель C:
Swift:
Для экземпляра метки в UITableviewCell
Примечание . Если у вас более одной метки (UIElements) с динамической длиной, которая должна быть отрегулирована в соответствии с размером ее содержимого: настройте «Приоритет содержания и сопротивления сжатию» для меток, которые вы хотите расширить / сжать с более высоким приоритетом.
источник
tableView: heightForRow
источника данных.tableView: heightForRow
. (для iOS 10tableView: heightForRow
- обязательно)tableView: heightForRow
..if (indexPath.row == 0) { return 100} else { return UITableView.automaticDimension }
Нравится @ Bob-Spryn я столкнулся с достаточно важной я в качестве ответа.
Некоторое время я боролся с ответом @ smileyborg . Гоча , что я столкнулся, если вы определили свой прототип ячейку в IB с дополнительными элементами (
UILabels
,UIButtons
и т.д.) в IB , когда экземпляр ячейки с [[YourTableViewCellClass alloc] init]
он не будет инстанцирует все остальные элементы в этой ячейке , если вы не имеете написанный код, чтобы сделать это. (У меня был похожий опыт сinitWithStyle
.)Чтобы заставить раскадровку создавать экземпляры всех дополнительных элементов, получите ячейку с
[tableView dequeueReusableCellWithIdentifier:@"DoseNeeded"]
(Не так,[tableView dequeueReusableCellWithIdentifier:forIndexPath:]
как это вызовет интересные проблемы.) Когда вы сделаете это, будут созданы все элементы, которые вы определили в IB.источник
Высота ячейки динамического представления таблицы и автоматическое расположение
Хороший способ решить проблему с раскадровкой Auto Layout:
источник
источник
Другое «решение»: пропустите все это разочарование и используйте вместо этого UIScrollView, чтобы получить результат, который выглядит и чувствует себя идентичным UITableView.
Это было болезненное «решение» для меня, после того, как я потратил буквально 20+ очень разочаровывающих часов, пытаясь создать что-то вроде того, что предложил смайлиборг, и потерпел неудачу в течение многих месяцев и трех версий выпусков App Store.
Я считаю, что если вам действительно нужна поддержка iOS 7 (для нас это важно), то эта технология слишком хрупкая, и вы попробуете. И этот UITableView, как правило, полностью излишним, если только вы не используете некоторые расширенные функции редактирования строк и / или действительно не нуждаетесь в поддержке более 1000 «строк» (в нашем приложении реально не более 20 строк).
Дополнительным бонусом является то, что код становится безумно простым по сравнению со всем дерьмом делегата и обратно, который идет с UITableView. Это всего лишь один цикл кода в viewOnLoad, который выглядит элегантно и прост в управлении.
Вот несколько советов о том, как это сделать:
Используя Storyboard или nib-файл, создайте ViewController и связанный корневой вид.
Перетащите на UIScrollView на ваш корневой вид.
Добавьте ограничения top, bottom, left и right к представлению верхнего уровня, чтобы UIScrollView заполнил весь корневой вид.
Добавьте UIView внутри UIScrollView и назовите его «контейнер». Добавьте верхний, нижний, левый и правый ограничения в UIScrollView (его родитель). КЛЮЧЕВЫЙ КЛЮЧ: также добавьте ограничения «Равная ширина», чтобы связать UIScrollView и UIView.
ПРИМЕЧАНИЕ. Появится сообщение об ошибке «представление прокрутки имеет неоднозначную высоту прокручиваемого содержимого» и что ваш контейнер UIView должен иметь высоту 0 пикселей. Кажется, ни одна ошибка не имеет значения, когда приложение работает.
Создайте nib-файлы и контроллеры для каждой из ваших «ячеек». Используйте UIView, а не UITableViewCell.
В своем корневом ViewController вы по существу добавляете все «строки» в контейнер UIView и программно добавляете ограничения, связывающие их левый и правый края с видом контейнера, их верхние края либо с верхом представления контейнера (для первого элемента), либо с предыдущим клетка. Затем свяжите последнюю ячейку с дном контейнера.
Для нас каждая «строка» находится в файле пера. Итак, код выглядит примерно так:
А вот код для UITools.addViewToTop:
Единственная «уловка», которую я обнаружил при таком подходе, заключается в том, что в UITableView есть приятная особенность «плавающих» заголовков разделов в верхней части представления при прокрутке. Вышеупомянутое решение не сделает этого, если вы не добавите больше программирования, но для нашего конкретного случая эта функция не была на 100% существенной, и никто не заметил, когда она ушла.
Если вы хотите, чтобы между вашими ячейками были разделители, просто добавьте UIView высотой 1 пиксель внизу вашей пользовательской «ячейки», которая выглядит как разделитель.
Обязательно включите «bounces» и «bounce vertical», чтобы элемент управления обновлением работал, и поэтому он больше похож на просмотр таблицы.
TableView показывает некоторые пустые строки и разделители под вашим контентом, если он не заполняет весь экран, где, как это решение не делает. Но лично я предпочитаю, если бы этих пустых строк в любом случае не было - с переменной высотой ячейки мне всегда казалось "глючным", чтобы пустые строки были там.
Мы надеемся, что какой-нибудь другой программист прочтет мой пост, ДО того, как потратит 20 с лишним часов, пытаясь выяснить это с помощью табличного представления в своем собственном приложении. :)
источник
Мне пришлось использовать динамические представления (настройки представления и ограничения по коду), и когда я захотел установить ширину метки предпочитаемыйMaxLayoutWidth, была равна 0. Поэтому у меня неправильная высота ячейки.
Потом я добавил
перед выполнением
После этого ширина метки была ожидаемой, а динамическая высота вычислялась правильно.
источник
Допустим, у вас есть ячейка с подпредставлением, и вы хотите, чтобы высота ячейки была достаточно высокой, чтобы охватить подпредставление + заполнение.
1) Установите нижнее ограничение подпредставления равным cell.contentView минус требуемый отступ. Не устанавливайте ограничения для ячейки или самого cell.contentView.
2) Установить либо Tableview в
rowHeight
собственности илиtableView:heightForRowAtIndexPath:
вUITableViewAutomaticDimension
.3) Установите либо
estimatedRowHeight
свойство tableView, либоtableView:estimatedHeightForRowAtIndexPath:
наилучшее предположение о высоте.Вот и все.
источник
Если вы делаете макет программно, вот что нужно учитывать для iOS 10 с использованием якорей в Swift.
Есть три правила / шаги
NUMBER 1: установите эти два свойства tableview в viewDidLoad, первое из которых сообщает табличному представлению, которое должно ожидать динамические размеры в их ячейках, второе - просто позволяет приложению рассчитать размер индикатора полосы прокрутки, поэтому это помогает представление.
НОМЕР 2: Это важно, вам нужно добавить подпредставления в contentView ячейки, а не в представление, а также использовать ее макет макета для привязки подпредставлений к верху и низу, это рабочий пример того, как это сделать.
Создайте метод, который добавит подпредставления и выполнит макет, вызовите его в методе init.
НОМЕР 3: НЕ ВЫЗЫВАЙТЕ МЕТОД:
Если вы сделаете это, вы переопределите свою реализацию.
Следуйте этим 3 правилам для динамических ячеек в табличных представлениях.
Вот рабочая реализация https://github.com/jamesrochabrun/MinimalViewController
источник
Если у вас есть длинная строка. например тот, который не разрыва строки. Тогда вы можете столкнуться с некоторыми проблемами.
«Предполагаемое» исправление упоминается в принятом ответе и нескольких других ответах. Вам просто нужно добавить
Я нахожу ответ Суры наиболее полным и лаконичным , а следовательно, не сбивающим с толку.
Хотя не объяснить, почему эти изменения необходимы. Давайте сделаем это.
Перетащите следующий код в проект.
Обратите внимание, что я не добавил размер ограничений по . Я только добавил centerX, centerY ограничения. Но все равно этикетка будет иметь правильный размер. Почему?
Из-за
contentSize
.Чтобы лучше это обработать, сначала сохраните шаг 0, а затем закомментируйте шаги 1-6. Пусть
setupLayout()
останутся. Соблюдайте поведение.Затем раскомментируйте шаг 1 и наблюдайте.
Затем раскомментируйте шаг 2 и наблюдайте.
Делайте это, пока вы не прокомментировали все 6 шагов и не наблюдали за их поведением.
Что можно сделать из всего этого? Какие факторы могут изменить
contenSize
?\n
то ширина intrinsicContentSize будет максимальной шириной всех строк. Если в одной строке 25 символов, в другой 2 символа, а в другой 21 символ, то ваша ширина будет рассчитана на основе 25 символов.numberOfLines
в0
противном случае вы не будете иметь несколько строк. ВыnumberOfLines
отрегулируете высоту вашего intrinsicContentSizeВнесение корректировок. Представьте, что на основе вашего текста ширина
200
и высота вашего intrinsicContentSize были100
, но вы хотели ограничить ширину контейнера метки, что вы собираетесь делать? Решение состоит в том, чтобы установить желаемую ширину. Вы делаете это, устанавливаяpreferredMaxLayoutWidth
значение130
затем, когда ваш новый intrinsicContentSize будет иметь ширину примерно130
. Высота, очевидно, будет больше, чем100
потому, что вам нужно больше линий. Тем не менее, если ваши ограничения установлены правильно, вам не нужно будет использовать это вообще! Подробнее об этом смотрите этот ответ и его комментарии. Вам нужно использовать толькоpreferredMaxLayoutWidth
если у вас нет ограничений, ограничивающих ширину / высоту, как можно было бы сказать «не переносить текст, если он не превышаетpreferredMaxLayoutWidth
». Но со 100% уверенностью , если вы установите ведущий / ведомый иnumberOfLines
в0
то вы хорошо!Короче говоря, большинство ответов здесь, которые рекомендуют использовать это НЕПРАВИЛЬНО! Тебе это не нужно. Необходимость в этом является признаком того, что ваши ограничения установлены неправильно или у вас просто нет ограниченийРазмер шрифта: также обратите внимание, что если вы увеличите свой fontSize, то высота intrinsicContentSize увеличится. Я не показал это в моем коде. Вы можете попробовать это самостоятельно.
Итак, вернемся к вашему примеру tableViewCell:
Все, что вам нужно сделать, это:
numberOfLines
To0
preferredMaxLayoutWidth
.источник
В моем случае я должен создать пользовательскую ячейку с изображением, которое приходит с сервера и может быть любой ширины и высоты. И две UILabels с динамическим размером (ширина и высота)
я достиг того же самого в моем ответе с autolayout и программно:
В основном выше @smileyBorg помог ответ, но systemLayoutSizeFittingSize у меня никогда не работал, в моем подходе:
1. Не использовать свойство автоматического расчета высоты строки. 2.Не использовать расчетную высоту 3.Не нужно ненужных обновлений ограничений. 4.Не использовать автоматическую максимальную ширину макета. 5. Не использовать systemLayoutSizeFittingSize (должен использовать, но не работает для меня, я не знаю, что он делает внутри), но вместо этого мой метод - (float) getViewHeight работает, и я знаю, что он делает внутри.
Можно ли иметь разную высоту в ячейке UITableView, когда я использую несколько разных способов отображения ячейки?
источник
В моем случае заполнение происходило из-за высоты sectionHeader и sectionFooter, где раскадровка позволила мне изменить его на минимум 1. Так что в методе viewDidLoad:
источник
Я просто сделал какую-то глупую попытку и ошибку с двумя значениями
rowHeight
иestimatedRowHeight
и просто подумал, что это может дать некоторое понимание отладки:Если вы установите их обоих ИЛИ только установите,
estimatedRowHeight
вы получите желаемое поведение:Предполагается, что вы делаете все возможное, чтобы получить правильную оценку, но конечный результат не отличается. Это просто повлияет на вашу производительность.
Если вы устанавливаете только rowHeight, т.е. только делаете:
Ваш конечный результат не будет таким, как хотелось бы:
Если вы установите
estimatedRowHeight
значение 1 или меньше, то произойдет сбой независимо отrowHeight
.Я разбился со следующим сообщением об ошибке:
источник
Что касается принятого ответа @smileyborg, я нашел
быть ненадежным в некоторых случаях, когда ограничения неоднозначны. Лучше заставить механизм макета вычислять высоту в одном направлении, используя категорию помощника на UIView ниже:
Где w: ширина таблицы
источник
Просто добавьте эти две функции в ваш viewcontroller, это решит вашу проблему. Здесь list - это строковый массив, который содержит вашу строку каждой строки.
источник
источник
Если высота ячейки является динамической по содержимому, вы должны точно отсчитать ее, а затем вернуть значение высоты до визуализации ячейки. Простой способ состоит в том, чтобы определить метод подсчета в коде ячейки табличного представления для вызова контроллером метода делегата высоты ячейки таблицы. Не забудьте подсчитать реальную ширину рамки ячейки (по умолчанию 320), если высота зависит от ширины таблицы или экрана. То есть в методе делегата высоты ячейки таблицы сначала используйте cell.frame, чтобы скорректировать ширину ячейки, а затем вызовите метод подсчета высоты, определенный в ячейке, чтобы получить подходящее значение и вернуть его .
PS. Код для создания объекта ячейки может быть определен в другом методе для вызова другого метода делегата ячейки табличного представления.
источник
UITableView.automaticDimension
может быть установлен через Interface Builder:Xcode> Раскадровка> Инспектор размеров
Ячейка табличного представления> Высота строки> Автоматически
источник
еще одно решение iOs7 + iOs8 в Swift
источник
cellForRowAtIndexPath
, ячейка еще не выложена в этой точке.