Создание UITableView со встроенным UICollectionView с использованием UITableViewAutomaticDimension
Я хочу создать UITableView
с меткой заголовка и встроенным UICollectionView
(который знает, что это размер) с некоторыми значками с помощью UITableViewAutomaticDimension
. Проблема UITableView
имеет проблему с определением высоты ячейки, когда у меня есть UICollectionView
внутри. Я должен прокрутить UITableView
для того, чтобы пересчитать размеры. Но даже тогда у него есть проблемы с высотой (это слишком большой, если он был повторно использован из большего). Поверх этого значков внутри UICollectionView
не известны из begginging, но они предназначены для загрузки от сервера.
Я также попытался создать ограничение высоты для UICollectionView
, но таким образом я получаю "неспособность одновременно удовлетворять ограничения", вызванные конфликтом с UIView-Encapsulated-Layout-Height
и мое собственное ограничение все равно удаляется.
Я создал репозиторий GitHub с образцом проекта (я сделал это как можно проще):
5 ответов
как вы делаете очень много вещей в cellForRow
поэтому ему нужно время, чтобы подготовиться, и поэтому при прокрутке он не отображается должным образом
проверьте следующие вещи.
ViewController.Свифт!--21-->
ввиду загрузки
добавить tableView.rowHeight = UITableViewAutomaticDimension
и замените этот метод
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let foo = foos[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! FooTableViewCell
cell.titleLabel.text = foo.title
cell.descriptionLabel.text = foo.description
self.view.layoutIfNeeded()
return cell
}
FooTableViewCell.Свифт!--21-->
class FooTableViewCell: UITableViewCell {
@IBOutlet weak var titleLabel: UILabel!
@IBOutlet weak var stackView: UIStackView!
@IBOutlet weak var descriptionLabel: UILabel!
@IBOutlet weak var iconsCollectionView: IconsCollectionView!
@IBOutlet weak var const_Height_CollectionView: NSLayoutConstraint!
override func awakeFromNib() {
iconsCollectionView.translatesAutoresizingMaskIntoConstraints = false
iconsCollectionView.initFlowLayout(superviewWidth: self.frame.width)
iconsCollectionView.loadIconsSync()
iconsCollectionView.setNeedsLayout()
}
}
и я удалил StackView форму вашего раскадровка и просто дайте ведущие, трейлинг, верхние и нижние ограничения (ничего сложного )
здесь выводится
надеюсь, что это полезно для вас
ИЗМЕНИТЬ/ОБНОВИТЬ
у вас есть много проблем в вашем демо-проекте. Я внес много изменений в ваш демо-проект.
копировать и вставлять XML
in раскадровка.
НЕ ЗАБУДЬТЕ ПОДКЛЮЧИТЬ ОГРАНИЧЕНИЕ ВЫСОТЫ
вот полная раскадровка XML
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13771" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13772"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="ViewController" customModule="CollectionViewInTableView" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="196" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="ZhZ-if-Yia">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<prototypes>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="cell" rowHeight="196" id="1WO-2S-MI9" customClass="FooTableViewCell" customModule="CollectionViewInTableView" customModuleProvider="target">
<rect key="frame" x="0.0" y="28" width="375" height="196"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="1WO-2S-MI9" id="2lF-aM-Z2U">
<rect key="frame" x="0.0" y="0.0" width="375" height="195.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Title" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="vs4-91-woo">
<rect key="frame" x="8" y="8" width="359" height="20.5"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Description" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="lD2-bR-lnm">
<rect key="frame" x="8" y="36.5" width="359" height="20.5"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<collectionView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" dataMode="prototypes" translatesAutoresizingMaskIntoConstraints="NO" id="6sQ-gf-Y6x" customClass="IconsCollectionView" customModule="CollectionViewInTableView" customModuleProvider="target">
<rect key="frame" x="8" y="65" width="359" height="92.5"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="height" relation="greaterThanOrEqual" priority="750" constant="88" id="f9g-Du-pYg"/>
</constraints>
<collectionViewFlowLayout key="collectionViewLayout" minimumLineSpacing="10" minimumInteritemSpacing="10" id="Nts-Lf-FPD">
<size key="itemSize" width="50" height="50"/>
<size key="headerReferenceSize" width="0.0" height="0.0"/>
<size key="footerReferenceSize" width="0.0" height="0.0"/>
<inset key="sectionInset" minX="0.0" minY="0.0" maxX="0.0" maxY="0.0"/>
</collectionViewFlowLayout>
<cells>
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="item" id="8gX-Q1-0jG" customClass="BarCollectionViewCell" customModule="CollectionViewInTableView" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="50" height="50"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO">
<rect key="frame" x="0.0" y="0.0" width="50" height="50"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="6cf-uD-BQl">
<rect key="frame" x="0.0" y="0.0" width="50" height="50"/>
</imageView>
</subviews>
</view>
<constraints>
<constraint firstAttribute="bottom" secondItem="6cf-uD-BQl" secondAttribute="bottom" id="0c3-ug-8tN"/>
<constraint firstItem="6cf-uD-BQl" firstAttribute="top" secondItem="8gX-Q1-0jG" secondAttribute="top" id="9xW-dN-c0m"/>
<constraint firstItem="6cf-uD-BQl" firstAttribute="leading" secondItem="8gX-Q1-0jG" secondAttribute="leading" id="dT6-RU-eE4"/>
<constraint firstAttribute="trailing" secondItem="6cf-uD-BQl" secondAttribute="trailing" id="nnz-oA-GgP"/>
</constraints>
<connections>
<outlet property="iconImageView" destination="6cf-uD-BQl" id="lFo-SS-Ego"/>
</connections>
</collectionViewCell>
</cells>
</collectionView>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="right" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="sXa-Mn-xxW">
<rect key="frame" x="8" y="165.5" width="359" height="30"/>
<state key="normal" title="Button"/>
</button>
</subviews>
<constraints>
<constraint firstItem="sXa-Mn-xxW" firstAttribute="leading" secondItem="2lF-aM-Z2U" secondAttribute="leading" constant="8" id="4ix-8u-0lO"/>
<constraint firstAttribute="bottom" secondItem="sXa-Mn-xxW" secondAttribute="bottom" id="50m-Bv-FF8"/>
<constraint firstAttribute="trailing" secondItem="sXa-Mn-xxW" secondAttribute="trailing" constant="8" id="8UW-vI-hge"/>
<constraint firstItem="6sQ-gf-Y6x" firstAttribute="leading" secondItem="2lF-aM-Z2U" secondAttribute="leading" constant="8" id="9ht-Ez-lJX"/>
<constraint firstAttribute="trailing" secondItem="vs4-91-woo" secondAttribute="trailing" constant="8" id="NOH-if-o7C"/>
<constraint firstItem="lD2-bR-lnm" firstAttribute="leading" secondItem="2lF-aM-Z2U" secondAttribute="leading" constant="8" id="S2D-Kj-5Og"/>
<constraint firstItem="vs4-91-woo" firstAttribute="leading" secondItem="2lF-aM-Z2U" secondAttribute="leading" constant="8" id="atk-7U-Mrw"/>
<constraint firstAttribute="trailing" secondItem="6sQ-gf-Y6x" secondAttribute="trailing" constant="8" id="bfY-uh-Su2"/>
<constraint firstItem="vs4-91-woo" firstAttribute="top" secondItem="2lF-aM-Z2U" secondAttribute="top" constant="8" id="gYO-XW-lmk"/>
<constraint firstAttribute="trailing" secondItem="lD2-bR-lnm" secondAttribute="trailing" constant="8" id="pkH-Pf-xE1"/>
<constraint firstItem="sXa-Mn-xxW" firstAttribute="top" secondItem="6sQ-gf-Y6x" secondAttribute="bottom" constant="8" id="w2O-4g-q6B"/>
<constraint firstItem="6sQ-gf-Y6x" firstAttribute="top" secondItem="lD2-bR-lnm" secondAttribute="bottom" constant="8" id="xky-sw-IcM"/>
<constraint firstItem="lD2-bR-lnm" firstAttribute="top" secondItem="vs4-91-woo" secondAttribute="bottom" constant="8" id="yG3-dE-CjF"/>
</constraints>
</tableViewCellContentView>
<connections>
<outlet property="const_Height_CollectionView" destination="f9g-Du-pYg" id="gw7-9T-hiU"/>
<outlet property="descriptionLabel" destination="lD2-bR-lnm" id="M4K-k5-6LN"/>
<outlet property="iconsCollectionView" destination="6sQ-gf-Y6x" id="FO2-dP-VNH"/>
<outlet property="titleLabel" destination="vs4-91-woo" id="HHy-1V-bTW"/>
</connections>
</tableViewCell>
</prototypes>
</tableView>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="ZhZ-if-Yia" firstAttribute="top" secondItem="8bC-Xf-vdC" secondAttribute="top" id="J8c-wQ-FxB"/>
<constraint firstItem="ZhZ-if-Yia" firstAttribute="bottom" secondItem="6Tk-OE-BBY" secondAttribute="bottom" id="KCX-nj-zXy"/>
<constraint firstItem="ZhZ-if-Yia" firstAttribute="leading" secondItem="6Tk-OE-BBY" secondAttribute="leading" id="QMU-w2-uUY"/>
<constraint firstItem="ZhZ-if-Yia" firstAttribute="trailing" secondItem="6Tk-OE-BBY" secondAttribute="trailing" id="yx7-yg-aqC"/>
</constraints>
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
</view>
<connections>
<outlet property="tableView" destination="ZhZ-if-Yia" id="WdR-nu-gjc"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="117.59999999999999" y="118.29085457271366"/>
</scene>
</scenes>
</document>
FOOTableviewCell.Свифт!--21-->
protocol TableViewDelegate {
func cellTapped (for:FooTableViewCell)
}
class FooTableViewCell: UITableViewCell {
static let singleCellHeight = 88;
@IBOutlet weak var titleLabel: UILabel!
@IBOutlet weak var descriptionLabel: UILabel!
@IBOutlet weak var iconsCollectionView: IconsCollectionView!
@IBOutlet weak var const_Height_CollectionView: NSLayoutConstraint!
var delegateCollection : TableViewDelegate?
var bars:[Bar] = [] {
didSet {
self.iconsCollectionView.reloadData()
iconsCollectionView.setNeedsLayout()
self.layoutIfNeeded()
const_Height_CollectionView.constant = iconsCollectionView.contentSize.height
self.layoutIfNeeded()
}
}
override func awakeFromNib() {
iconsCollectionView.translatesAutoresizingMaskIntoConstraints = false
iconsCollectionView.initFlowLayout(superviewWidth: self.frame.width)
iconsCollectionView.setNeedsLayout()
iconsCollectionView.dataSource = self
iconsCollectionView.delegate = self
const_Height_CollectionView.constant = iconsCollectionView.contentSize.height
self.layoutIfNeeded()
self.setNeedsLayout()
}
func cellTapped () {
iconsCollectionView.setNeedsLayout()
self.layoutIfNeeded()
self.setNeedsLayout()
const_Height_CollectionView.constant = iconsCollectionView.contentSize.height
self.delegateCollection?.cellTapped(for: self)
}
}
extension FooTableViewCell : UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return bars.count + 1
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "item", for: indexPath) as! BarCollectionViewCell
let row = indexPath.row
if(row >= bars.count) {
cell.iconImageView.image = UIImage(named: "add.png")
return cell
} else {
let bar = bars[row]
cell.iconImageView.image = UIImage(named: bar.imageName)
print(bar.imageName)
return cell
}
}
}
extension FooTableViewCell : UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
//deselectItem(at: indexPath, animated: true)
if(indexPath.row >= bars.count) { //it's a plus button
self.delegateCollection?.cellTapped(for: self)
}
}
}
IconCollectionView.Свифт!--21-->
import UIKit
class IconsCollectionView: DynamicCollectionView {
var columnLayout:ColumnFlowLayout?
override func awakeFromNib() {
}
func initFlowLayout(superviewWidth:CGFloat) {
let layout = ColumnFlowLayout(
cellsPerRow: 4,
superviewWidth: superviewWidth,
minimumInteritemSpacing: 0,
minimumLineSpacing: 0,
sectionInset: UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
)
columnLayout = layout
collectionViewLayout = layout
}
}
ViewController.Свифт!--21-->
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var tableView: UITableView!
var foos:[Foo] = []
var bars:[[Bar]] = [[]]
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.delegate = self
tableView.estimatedRowHeight = 188
tableView.rowHeight = UITableViewAutomaticDimension
for i in stride(from: 1, to: 10, by: 1) {
let foo = Foo()
foo.title = "Item \(i)"
foo.description = "Description \(i)"
foos.append(foo)
}
bars.removeAll()
for _ in 0 ..< foos.count {
bars.append(self.loadIconsSync())
}
}
func loadIconsSync() -> [Bar] {
var barObjects :[Bar] = []
let iconsCount = Utils.rnd(3, 8)
for _ in stride(from: 1, to: iconsCount, by: 1) {
barObjects.append(self.getRandomItem())
}
return barObjects
}
func getRandomItem() -> Bar {
let randomIndex = Utils.rnd(1, 10)
let bar = Bar()
bar.imageName = "icon_\(randomIndex).png"
return bar
}
}
extension ViewController : UITableViewDataSource,UITableViewDelegate {
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let foo = foos[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! FooTableViewCell
var bar = bars[indexPath.row]
cell.bars = bar
cell.titleLabel.text = foo.title
cell.descriptionLabel.text = foo.description
cell.delegateCollection = self
self.view.layoutIfNeeded()
cell.const_Height_CollectionView.constant = cell.iconsCollectionView.contentSize.height
self.view.layoutIfNeeded()
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return foos.count
}
}
extension ViewController : TableViewDelegate {
func cellTapped(for obj: FooTableViewCell) {
if let indexPath = tableView.indexPath(for: obj) {
bars[indexPath.row].append(getRandomItem())
self.tableView.beginUpdates()
self.tableView.reloadRows(at: [indexPath], with: .automatic)
self.tableView.endUpdates()
}
}
}
выход
изменить / Обновление 2
я не знал о поддержке ориентации и поддержке ipad.
теперь, когда ориентация изменяется, мы должны перестроить представление коллекции.
Итак, логика
всего элементов + 1 (+1 из-за этого плюс значок )
размер элемента * (всего элементов / 3).округлые
предположим, у вас есть 7 пунктов
так размер деталя 93 (в строку) * (8 / 3).округлый = 279
так вот вам нужно управлять некоторыми жестко закодированными значениями в соответствии с вашими требованиями для iPad и ландшафтного режима. На данный момент я рассматриваю 3 объекта в строке так же, как дизайн iPhone.
здесь Hardcoded номер ячейки 3 Вы можете управлять своими собственными.
Шаг 1:
добавить следующий метод в viewContorller.Свифт!--16-->
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
self.tableView.beginUpdates()
self.tableView.reloadData()
self.tableView.endUpdates()
}
заменить cellForRowAtIndexPath
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let foo = foos[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! FooTableViewCell
cell.iconsCollectionView.initFlowLayout(superviewWidth: self.tableView.frame.width)
let bar = bars[indexPath.row]
cell.bars = bar
cell.titleLabel.text = foo.title
cell.descriptionLabel.text = foo.description
cell.delegateCollection = self
self.view.layoutIfNeeded()
let items:CGFloat = CGFloat(bar.count + 1)
let value = (items / 3.0).rounded(.awayFromZero)
cell.const_Height_CollectionView.constant = CGFloat((cell.iconsCollectionView.collectionViewLayout as! UICollectionViewFlowLayout).itemSize.height * value)
self.view.layoutIfNeeded()
cell.iconsCollectionView.setNeedsLayout()
return cell
}
и
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
if let footCell = cell as? FooTableViewCell {
footCell.const_Height_CollectionView.constant = footCell.iconsCollectionView.contentSize.height
self.view.layoutIfNeeded()
}
}
In TableviewCell
var bars:[Bar] = [] {
didSet {
self.iconsCollectionView.reloadData()
iconsCollectionView.setNeedsLayout()
self.layoutIfNeeded()
let items:CGFloat = CGFloat(bars.count + 1)
let value = (items / 3.0).rounded(.awayFromZero)
const_Height_CollectionView.constant = CGFloat((iconsCollectionView.collectionViewLayout as! UICollectionViewFlowLayout).itemSize.height * value)
self.layoutIfNeeded()
}
}
и
func cellTapped () {
iconsCollectionView.setNeedsLayout()
self.layoutIfNeeded()
self.setNeedsLayout()
let items:CGFloat = CGFloat(bars.count + 1)
let value = (items / 3.0).rounded(.awayFromZero)
const_Height_CollectionView.constant = CGFloat((iconsCollectionView.collectionViewLayout as! UICollectionViewFlowLayout).itemSize.height * value)
self.delegateCollection?.cellTapped(for: self)
}
Я думаю, вам нужно реализовать estimatedHeightForRowAt
, поэтому вместо метода ниже
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
использовать ниже метод:
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
Это должно работать, попробуйте!
UICollectionView
сам по себе не имеет внутреннего размера контента, поэтому вам нужно создать явное ограничение высоты для него, как вы говорите.
если макет, кажется, работает, но вы получаете неудовлетворительные ограничения с UIView-Encapsulated-Layout-Height
, тогда прочитайте следующие.
это результат того, как UITableViewAutomaticDimension
works-он устанавливает высоту ячейки на основе некоторого значения по умолчанию (я все еще не знаю, как он получает это значение), затем использует autolayout для вычисления высота вашей ячейки хочет, а затем обновляет UIView-Encapsulated-Layout-Height
чтобы соответствовать новой высоты. Но в процессе ваши ограничения и UIView-Encapsulated-Layout-Height
ограничение вступает в конфликт. Решение состоит в том, чтобы установить приоритет одного из ваших ограничений на collectionViewHeightConstraint.priority = UILayoutPriority(rawValue: 999)
. Таким образом, ограничения не будут нарушены, и autolayout будет работать без предупреждений + обратите внимание, что в конце UIView-Encapsulated-Layout-Height
будет обновляться до нужной высоты, поэтому снижение приоритета не помешает макету работать. См.мой ответ: к другому подобному вопрос Для справки.
редактировать
я разветвил ваш проект, исправил его и создал запрос на вытягивание (см. github).
основная проблема, я считаю, была очень тривиальной ошибкой. Вы использовали bars.count
чтобы рассчитать внутренний размер коллекции, но в конце концов у вас было bars.count + 1
элементов в коллекции (значок+). Поэтому, если значок + должен был быть помещен в новую строку, казалось, что ваш макет не работает.
так просто изменить
let rows = ceil(Double(bars.count) / Double(columnLayout.cellsPerRow))
to
let rows = ceil(Double(bars.count + 1) / Double(columnLayout.cellsPerRow))
на intrinsicContentSize
на IconsCollectionView
.
были другие вещи, которые я бы изменил, и я изменил его в проекте - в прототипе вашей ячейки в раскадровках.
во-первых, я удалил это явное ограничение на высоту набора коллекции, равную 88 точкам. У вас есть внутренний размер, поэтому вам это не нужно (если раскадровки жалуются, не обращайте на них внимания, они не знают, что вы реализовали внутренний размер.
во-вторых, кнопка внизу не была ограничена нижней частью ячейки. Таким образом, расчет высоты ячейки не может работать (вы хотите, чтобы размер ячейки соответствовал ее содержимому, поэтому вам нужно ограничить все стороны ячейки ее содержимым). Но это, возможно, было результатом чьих-то советов, потому что я думаю, что старые коммиты работали.
в-третьих, незначительная нота, к тому, как вы использовали superviewWidth
для расчета размера. Я изменил его на selfView
, и изменил способ вычисления его значения. Потому что в конце ширина представления коллекции не равна ширине ячейки, а ширине ячейки -16. Это потому, что collectionView был ограничен, чтобы начать 8 точек слева от ячейки contentView
, и 8 точек справа от ячейки contentView
. Хотя это не главная проблема, она может вызвать некоторые проблемы позже.
наконец, я оставил вам комментарий в асинхронной загрузке элементов. Если вы загрузите его асинхронно ячейка, скорее всего, будет представлена до того, как вы получите свои данные, и вы захотите обновить tableView для адаптации к недавно загруженным данным. Концептуально это то же самое, что динамически расширяющиеся и коллапсирующие ячейки - для этого я отсылаю вас к мой ответ на этот вопрос.
Я загрузил исходный код Git hub и исправил проблему. Ваш код идеально подходит для установки размера ячейки , проблема заключается в компоновке потока столбцов. Вы устанавливали отображение 4 ячеек подряд, но в соответствии с вашим исходным кодом отображалось только 3 ячейки.Я копнул глубже и обнаружил, что из-за этого количество ячеек вычисляется неправильно в вашем "intrinsicContentSize" в представлении коллекции значков. Ширина super view, которую вы передаете в функции компоновки потока, вызывает проблема. я думаю, была какая-то проблема с расстоянием для ширины. Итак, вот как выглядит мой новый код:
override var itemSize: CGSize {
get {
let itemWidth = ((superviewWidth - 50) / CGFloat(cellsPerRow)).rounded(.down)
return CGSize(width: itemWidth, height: itemWidth)
}
set {
super.itemSize = newValue
}
}
override var intrinsicContentSize: CGSize {
guard let columnLayout = columnLayout else { return CGSize(width: 0, height: 0) }
let itemSize = columnLayout.itemSize
let rows = ceil(Double(bars.count) / Double(columnLayout.cellsPerRow))
let w = columnLayout.superviewWidth
let h = itemSize.height * CGFloat(rows)
print("itemSize: \(itemSize.width), \(itemSize.height), intrinsicContentSize: \(w), \(h); rows = \(rows)")
return CGSize(width: w, height: h)
}
Я изменил только эти две функции и ваш код прекрасно работал.
Если вы хотите исходный код, я могу нажать его на git тоже. Надеюсь, это поможет вам!
проблема :
// In DynamicCollectionView, when the icons fetch is not yet finished
override var intrinsicContentSize: CGSize {
return contentSize.height // == 0
}
таким образом, tableView не вычисляет правильные высоты ячеек.
решение дать по вашему collectionView
высота, когда вы получаете значки. Затем, когда fetch будет сделано, спросите ваш tableView для перезагрузки соответствующей строки. Поэтому вы должны основывать свой расчет высоты на макете вашего collectionView
а не contenSize
высота: the contenSize
на collectionView
может быть неправильным потому что reloadData
на самом деле асинхронные.