Один из экранов нашего приложения требует, чтобы мы поместили UICollectionView
внутри файла UITableViewCell
. Это UICollectionView
будет иметь динамическое количество элементов, в результате чего высота также должна вычисляться динамически. Однако я сталкиваюсь с проблемами при попытке рассчитать высоту встроенного UICollectionView
.
Наша общая структура UIViewController
была создана в раскадровках и действительно использует автоматический макет. Но я не знаю, как динамически увеличивать высоту в UITableViewCell
зависимости от высоты UICollectionView
.
Кто-нибудь может дать несколько советов или советов о том, как этого добиться?
ios
uitableview
uicollectionview
Shadowman
источник
источник
UITableViewCell
отличается от его фактического вида на столе? Нужна ли вертикальная прокрутка как на, такUICollectionView
и наUITableView
Ответы:
Правильный ответ - ДА , МОЖНО это сделать.
Я столкнулся с этой проблемой несколько недель назад. На самом деле это проще, чем вы думаете. Поместите свои ячейки в NIB (или раскадровки) и закрепите их, чтобы автоматическая компоновка выполняла всю работу
Учитывая следующую структуру:
Решение состоит в том, чтобы указать автоматическому макету сначала вычислить размеры collectionViewCell, затем - contentSize представления коллекции и использовать его как размер вашей ячейки. Это метод UIView, который «творит чудеса»:
Вы должны установить здесь размер TableViewCell, который в вашем случае является contentSize CollectionView.
CollectionViewCell
В CollectionViewCell вы должны указывать ячейке макет каждый раз, когда вы меняете модель (например: вы устанавливаете UILabel с текстом, тогда ячейка снова должна быть макетом).
TableViewCell
TableViewCell делает магию. Она имеет выход к вашему CollectionView, включает автоматическое расположение для ячеек CollectionView с использованием estimatedItemSize из UICollectionViewFlowLayout .
Затем уловка состоит в том, чтобы установить размер ячейки tableView в systemLayoutSizeFittingSize методе ... (ПРИМЕЧАНИЕ: iOS8 или новее)
ПРИМЕЧАНИЕ. Я попытался использовать метод высоты ячейки делегата для tableView.
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
Но для системы автоматической компоновки уже слишком поздно вычислять размер CollectionView contentSize, и иногда вы можете найти ячейки с неправильным размером.TableViewController
Не забудьте включить систему автоматического макета для ячеек tableView в вашем TableViewController :
КРЕДИТ: @rbarbera помог разобраться в этом
источник
cell.bounds = CGRectMake(0, 0, CGRectGetWidth(tableView.bounds), 10000);
это будет «имитировать» длинную ячейку с длинным collectionView, поэтому collectionView вычислит размер всех своих ячеек. В противном случае collectionView вычислял только видимые размеры ячеек и неверно устанавливал высоту talbeViewCell.systemLayoutSizeFittingSize
я быстро столкнулся с проблемой при перезагрузке ячейки, приложения, кажется, зависают послеself.collectionView.layoutIfNeeded()
. Я исправил это, установив высоту рамки на 1, а не на максимальную высоту. Надеюсь, это поможет, если кто-нибудь наткнется на эту проблему.systemLayoutSizeFitting
обратном порядке того, что показано в ответе в настоящее время, так что сначалаcollectionView.layoutIfNeeded()
запускается, а затемcollectionView.frame = CGRect.init(origin: .zero, size: CGSize.init(width: targetSize.width, height: 1))
Я думаю, что мое решение намного проще, чем предложенное @PabloRomeu.
Шаг 1. Создайте розетку из
UICollectionView
вUITableViewCell subclass
, где онаUICollectionView
находится. Пусть это будет имяcollectionView
Шаг 2. Добавьте IB для
UICollectionView
ограничения высоты и также создайте выходUITableViewCell subclass
. Пусть, имя будетcollectionViewHeight
.Шаг 3.
tableView:cellForRowAtIndexPath:
Добавьте код:источник
collectionView
всех сторонUITableViewCell
и устанавливаюtableView.estimatedRowHeight = 44;
иtableView.rowHeight = UITableViewAutomaticDimension;
Как представления таблиц, так и представления коллекций являются
UIScrollView
подклассами и поэтому не любят встраиваться в другое представление прокрутки, поскольку они пытаются вычислить размеры содержимого, повторно использовать ячейки и т. Д.Я рекомендую вам использовать только представление коллекции для всех ваших целей.
Вы можете разделить его на разделы и «рассматривать» макет некоторых разделов как вид таблицы, а других как вид коллекции. В конце концов, в представлении коллекции нет ничего, чего нельзя добиться в представлении таблицы.
Если у вас есть базовая сетка для «частей» представления коллекции, вы также можете использовать обычные ячейки таблицы для их обработки. Тем не менее, если вам не нужна поддержка iOS 5, вам лучше использовать представления коллекций.
источник
layoutAttributesForItemAtIndexPath
на разные разделы в моем собственном подклассеUICollectionViewLayout
?Ответ Пабло Ромеу выше ( https://stackoverflow.com/a/33364092/2704206 ) очень помог мне с моей проблемой. Однако мне пришлось сделать несколько вещей по-другому, чтобы это сработало для моей проблемы. Во-первых, мне пришлось не
layoutIfNeeded()
так часто звонить . Мне нужно было только вызвать егоcollectionView
вsystemLayoutSizeFitting
функции.Во-вторых, у меня были ограничения автоматической компоновки в моем представлении коллекции в ячейке табличного представления, чтобы дать ему некоторый отступ. Поэтому мне пришлось вычесть начальное и конечное поля из
targetSize.width
при установкеcollectionView.frame
ширины. Мне также пришлось добавить верхнее и нижнее поля кCGSize
высоте возвращаемого значения .Чтобы получить эти константы ограничений, у меня была возможность либо создать выходы для ограничений, жестко закодировать их константы, либо найти их по идентификатору. Я решил выбрать третий вариант, чтобы мой класс ячеек пользовательского табличного представления можно было легко повторно использовать. В конце концов, это было все, что мне нужно, чтобы все заработало:
В качестве вспомогательной функции для получения ограничения по идентификатору я добавляю следующее расширение:
ПРИМЕЧАНИЕ. Вам нужно будет установить идентификатор для этих ограничений в раскадровке или там, где они создаются. Если у них нет константы 0, это не имеет значения. Кроме того, как и в ответе Пабло, вам нужно будет использовать
UICollectionViewFlowLayout
в качестве макета для представления вашей коллекции. Наконец, убедитесь, что вы связалиcollectionView
IBOutlet со своей раскадровкой.С пользовательской ячейкой табличных выше, теперь я могу подкласс в любой другом виде таблицы ячейке , которая нуждается в представлении коллекции и он реализовать
UICollectionViewDelegateFlowLayout
иUICollectionViewDataSource
протоколы. Надеюсь, это поможет кому-то другому!источник
Прочитал все ответы. Кажется, это подходит для всех случаев.
источник
Альтернативой решению Пабло Ромеу является настройка самого UICollectionView, а не выполнение работы в ячейке табличного представления.
Основная проблема заключается в том, что по умолчанию представление коллекции не имеет внутреннего размера и поэтому не может информировать автоматический макет об используемых измерениях. Вы можете исправить это, создав собственный подкласс, который действительно возвращает полезный внутренний размер.
Создайте подкласс UICollectionView и переопределите следующие методы
(Вы также должны переопределить связанные методы: reloadSections, reloadItemsAtIndexPaths аналогично reloadData ())
Вызов layoutIfNeeded заставляет представление коллекции пересчитать размер содержимого, который затем можно использовать в качестве нового внутреннего размера.
Кроме того, вам необходимо явно обрабатывать изменения размера представления (например, при повороте устройства) в контроллере табличного представления.
источник
Недавно я столкнулся с той же проблемой, и я почти пробовал каждое решение в ответах, некоторые из них работали, а другие не беспокоились о подходе @PabloRomeu в том, что если у вас есть другое содержимое в ячейке (кроме представления коллекции) вам нужно будет вычислить их высоту и высоту их ограничений и вернуть результат, чтобы получить правильную автоматическую компоновку, а я не люблю вычислять вещи вручную в моем коде. Итак, вот решение, которое отлично сработало для меня, не выполняя никаких ручных вычислений в моем коде.
в виде
cellForRow:atIndexPath
таблицы я делаю следующее:Я думаю, что здесь происходит то, что я заставляю ячейку tableview регулировать свою высоту после вычисления высоты представления коллекции. (после предоставления источнику данных даты collectionView)
источник
Я бы поместил статический метод в класс представления коллекции, который будет возвращать размер в зависимости от содержимого, которое он будет иметь. Затем используйте этот метод в,
heightForRowAtIndexPath
чтобы вернуть правильный размер.Также обратите внимание, что вы можете получить странное поведение при встраивании таких видов viewControllers. Я сделал это однажды, и у меня возникли странные проблемы с памятью, с которыми я никогда не справлялся.
источник
Может быть, мой вариант будет полезен; Решал эту задачу последние два часа. Я не претендую на 100% правильность или оптимальность, но мои навыки еще очень малы, и я хотел бы услышать комментарии от экспертов. Спасибо. Одно важное замечание: это работает для статической таблицы - это указано в моей текущей работе. Итак, все, что я использую, это viewWillLayoutSubviews для tableView . И еще немного.
источник
Самый простой подход, который я придумал до сих пор, Кредиты на ответ @igor выше,
В вашем классе tableviewcell просто вставьте это
и, конечно же, замените collectionviewoutlet своим выходом в классе ячейки
источник
Я получил идею из сообщения @Igor и трачу свое время на это для моего проекта с помощью swift
Просто мимо этого в вашем
Дополнение: если вы видите, что ваш UICollectionView прерывистый при загрузке ячеек.
источник
Решение Пабло не очень хорошо сработало для меня, у меня были странные визуальные эффекты (collectionView не настраивается правильно).
Что сработало, так это отрегулировать ограничение высоты collectionView (как NSLayoutConstraint) на collectionView contentSize во время
layoutSubviews()
. Это метод, который вызывается, когда к ячейке применяется автоматическое размещение.источник
В вашем UITableViewDelegate:
Замените itemCount и CollectionViewCellHeight реальными значениями. Если у вас есть массив массивов, itemCount может быть:
Или как там.
источник
collectionViewCellHeight
до рендеринга.1.Создайте фиктивную ячейку.
2. Используйте метод collectionViewContentSize в UICollectionViewLayout из UICollectionView, используя текущие данные.
источник
Вы можете рассчитать высоту коллекции на основе его свойств , таких как
itemSize
,sectionInset
,minimumLineSpacing
,minimumInteritemSpacing
, если вашиcollectionViewCell
имеют границу правила.источник