带有约束的嵌套集合视图的意外行为(Swift 4)
Posted
技术标签:
【中文标题】带有约束的嵌套集合视图的意外行为(Swift 4)【英文标题】:Unexpected behavior with nested collection views with constraints (Swift 4) 【发布时间】:2018-04-16 05:38:00 【问题描述】:我在一个包含水平分页集合视图的表格视图中有一个单元格。
在此集合视图的每个页面内都有一个垂直集合视图。
为了避免“scroll-in-scroll”问题,我在垂直集合视图中禁用了垂直滚动。
垂直集合视图的单元格计数不是静态的,可以是任意数字。
所以这会产生一个问题:集合视图(您必须询问我以澄清哪个)不再适合表格视图的单元格。
为了解决这个问题,我通过更改情节提要中的约束来更改表格视图的单元格高度......但问题仍然存在。
这里有一张图片来帮助说明问题:
这是我的代码:
class myTBViewController: UITableViewController , UICollectionViewDelegate , UICollectionViewDataSource , UICollectionViewDelegateFlowLayout
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
if collectionView.tag == 10
return 2
else
return 30
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
if collectionView.tag == 10
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "mainPages", for: indexPath) as! mainPages
cell.backgroundColor = UIColor.yellow
cell.listCV.clipsToBounds = true
return cell
else
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "showAdvCell", for: indexPath) as! showAdvCell
cell.backgroundColor = UIColor.red
return cell
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets
if collectionView.tag == 10
let collectionViewHeight = collectionView.frame.height
let itemsHeight = collectionView.contentSize.height
let topInset = ( collectionViewHeight - itemsHeight ) / 4
return UIEdgeInsetsMake(topInset ,0, 0 , 0)
else
let collectionViewHeight = collectionView.frame.height
let itemsHeight = CGFloat(80)
let topInset = ( collectionViewHeight - itemsHeight ) / 4
return UIEdgeInsetsMake(topInset ,0, 0 , 0)
var headerSegment = UISegmentedControl()
override func viewDidLoad()
super.viewDidLoad()
headerSegment.frame = CGRect(x: 0, y: 200, width: UIScreen.main.bounds.width, height: 30)
let items = ["فروشگاه ها", "دیوار"]
headerSegment = UISegmentedControl(items: items)
headerSegment.selectedSegmentIndex = 0
headerSegment.addTarget(self, action: #selector(selectPage), for: UIControlEvents.valueChanged)
let frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 200)
let headerImageView = UIImageView(frame: frame)
let image: UIImage = UIImage(named: "1")!
headerImageView.image = image
let frame3 = CGRect(x: 0, y: 0, width: 80, height: 80)
let headerImageView2 = UIImageView(frame: frame3)
let image2: UIImage = UIImage(named: "1")!
headerImageView2.image = image2
headerSegment.addSubview(headerImageView2)
headerSegment.bringSubview(toFront: headerImageView2)
headerImageView2.center = CGPoint(x: UIScreen.main.bounds.width / 2, y: 200)
headerSegment.frame = CGRect(x: 0, y: 200, width: UIScreen.main.bounds.width + 10 , height: 40)
headerSegment.center = CGPoint(x: UIScreen.main.bounds.width / 2, y: 200)
let mainView = UIView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 230))
let headerSegmentView = UIView(frame : CGRect(x: 0, y: 200, width: UIScreen.main.bounds.width, height: 40))
headerSegmentView.center = headerSegment.center
headerSegmentView.backgroundColor = UIColor.white
mainView.addSubview(headerImageView)
mainView.bringSubview(toFront: headerImageView)
mainView.addSubview(headerSegmentView)
mainView.bringSubview(toFront: headerSegmentView)
mainView.addSubview(headerSegment)
mainView.bringSubview(toFront: headerSegment)
mainView.addSubview(headerImageView2)
mainView.bringSubview(toFront: headerImageView2)
self.tableView.tableHeaderView = mainView
headerImageView2.layer.borderWidth = 2
headerImageView2.layer.masksToBounds = false
headerImageView2.layer.borderColor = UIColor.init(white: 255/255, alpha: 0.3).cgColor
headerImageView2.layer.cornerRadius = headerImageView2.frame.height/2
headerImageView2.clipsToBounds = true
@objc func selectPage()
let cell = self.tableView.dequeueReusableCell(withIdentifier: "myTBViewCell") as! myTBViewCell
switch headerSegment.selectedSegmentIndex
case 0:
print("0")
cell.myTBCollectionView.scrollToItem(at:IndexPath(item: 0, section: 0), at: .top, animated: false)
case 1:
print("1")
cell.myTBCollectionView.scrollToItem(at:IndexPath(item: 1, section: 0), at: .top, animated: false)
default:
print("0")
cell.myTBCollectionView.scrollToItem(at:IndexPath(item: 0, section: 0), at: .top, animated: false)
override func didReceiveMemoryWarning()
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
override func numberOfSections(in tableView: UITableView) -> Int
// #warning Incomplete implementation, return the number of sections
return 1
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
// #warning Incomplete implementation, return the number of rows
return 1
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
tableView.estimatedRowHeight = 200
tableView.rowHeight = UITableViewAutomaticDimension
return 600
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
let cell = self.tableView.dequeueReusableCell(withIdentifier: "myTBViewCell", for: indexPath) as! myTBViewCell
return cell
【问题讨论】:
所以你想要增加集合视图的大小取决于集合视图中的单元格数量? 是的,适合表格视图单元格 您需要计算TableViewCell
in override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
中的预期高度
正如你在代码中看到的那样,我使用了这个函数但问题是,如果我使用数字,我会看到一些类似图片的东西,如果我使用自动尺寸,表格视图单元格不会是我所期待的事情,所以这是另一个人的问题,请也看到这个github.com/ashfurrow/Collection-View-in-a-Table-View-Cell/…
【参考方案1】:
我也有类似的问题,最后通过创建CollectionView的高度约束解决了。
比基于 CollectionView ContentSize 设置 CollectionView 高度约束。
self.collectionViewHeight.constant = self.recentCollectionView.collectionViewLayout.collectionViewContentSize.height
另一种方法是覆盖 tableViewCell 的 systemLayoutSizeFitting 方法
例如:
override func systemLayoutSizeFitting(_ targetSize: CGSize, withHorizontalFittingPriority horizontalFittingPriority: UILayoutPriority, verticalFittingPriority: UILayoutPriority) -> CGSize
super.systemLayoutSizeFitting(targetSize, withHorizontalFittingPriority: horizontalFittingPriority, verticalFittingPriority: verticalFittingPriority)
self.tagCollectionView.layoutIfNeeded()
return self.tagCollectionView.collectionViewLayout.collectionViewContentSize
此外,您不需要在表格视图委托 heightForRowAtIndexPath 中返回固定的 600 高度
【讨论】:
这个是用什么方法设置的? 这取决于需求。我在分配数据源后设置它。 func configure(model: [DaysModel], at indexPath: IndexPath) self.dataSource = model self.daysCollectionView.reloadData() daysCollectionViewHeight.constant = daysCollectionView.collectionViewLayout.collectionViewContentSize.height以上是关于带有约束的嵌套集合视图的意外行为(Swift 4)的主要内容,如果未能解决你的问题,请参考以下文章
将子视图添加到 UICollectionViewCell 时出现意外行为
我的带有自动布局约束的 Swift 4 UIScrollView 没有滚动