如何解决如何在 UICollectionViewCell 内制作完全展开的 TableView?
我正在尝试以编程方式在 UICollectionViewCell 中创建一个 tableview。我看到了其他问题,但他们似乎在使用 AutoLayout。我能够获取要显示的数据,但是我的单元格无法正确显示。无论我做什么,这些细胞似乎都以一种或另一种方式重叠。我需要在 UICollectionViewCell 内完全展开 tableview。
import Foundation
import UIKit
import MaterialComponents
class FollowingItemCollectionViewCell: MDCCardCollectionCell,UITableViewDataSource,UITableViewDelegate {
static let Identifer = "FollowingItemCollectionViewCell"
private var title: UILabel!
private var viewMoreButton: MDCButton!
private var tableView: SelfSizingTableView!
private var items: [Any] = []
private var item: FollowingItem!
private var clickListener: (FollowingItemClick) -> Void = { _ in }
override init(frame: CGRect) {
super.init(frame: frame)
createView()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
createView()
}
override func layoutSubviews() {
super.layoutSubviews()
backgroundColor = Colors.Card.background
}
private func createView() {
backgroundColor = Colors.Card.background
createTitle()
createTableView()
createViewMoreButton()
}
private func createTitle() {
title = UILabel()
title.font = UIFont(name: "HelveticaNeue-Bold",size: 24)
title.translatesAutoresizingMaskIntoConstraints = false
title.textColor = Colors.Card.text
contentView.addSubview(title)
title.topAnchor.constraint(equalTo: contentView.topAnchor,constant: 2).isActive = true
title.leadingAnchor.constraint(equalTo: contentView.leadingAnchor,constant: 8).isActive = true
title.trailingAnchor.constraint(equalTo: contentView.trailingAnchor,constant: -2).isActive = true
}
private func createTableView() {
tableView = SelfSizingTableView()
tableView.translatesAutoresizingMaskIntoConstraints = false
tableView.delegate = self
tableView.dataSource = self
tableView.register(ArticleUiTableViewCell.self,forCellReuseIdentifier: ArticleUiTableViewCell.Identifier)
tableView.register(SearchTableViewCell.self,forCellReuseIdentifier: SearchTableViewCell.Identifier)
tableView.backgroundColor = Colors.Card.background
let titleGuide = UILayoutGuide()
contentView.addSubview(tableView)
contentView.addLayoutGuide(titleGuide)
titleGuide.bottomAnchor.constraint(equalTo: title.bottomAnchor).isActive = true
tableView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor).isActive = true
tableView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor).isActive = true
tableView.topAnchor.constraint(equalTo: titleGuide.bottomAnchor).isActive = true
tableView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
}
private func createViewMoreButton() {
viewMoreButton = MDCButton()
viewMoreButton.translatesAutoresizingMaskIntoConstraints = false
viewMoreButton.setBackgroundColor(Colors.clear)
viewMoreButton.setTitleColor(Colors.royal,for: .normal)
viewMoreButton.addTarget(self,action: #selector(onViewMoreClick),for: .touchUpInside)
let tableViewGuide = UILayoutGuide()
contentView.addSubview(viewMoreButton)
contentView.addLayoutGuide(tableViewGuide)
tableViewGuide.bottomAnchor.constraint(equalTo: tableView.bottomAnchor).isActive = true
viewMoreButton.topAnchor.constraint(equalTo: tableViewGuide.bottomAnchor).isActive = true
viewMoreButton.leadingAnchor.constraint(equalTo: contentView.leadingAnchor).isActive = true
viewMoreButton.trailingAnchor.constraint(equalTo: contentView.trailingAnchor).isActive = true
}
@objc func onViewMoreClick() {
if item is FollowingSearchItem {
clickListener(FollowingItemClick.SearchViewMoreClick)
} else if item is FollowingArticleItem {
clickListener(FollowingItemClick.ArticleViewMoreClick)
}
}
func numberOfSections(in tableView: UITableView) -> Int {
1
}
func tableView(_ tableView: UITableView,numberOfRowsInSection section: Int) -> Int {
items.count
}
func tableView(_ tableView: UITableView,cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let item = items[indexPath.row]
if let item = item as? Article {
let cell = ArticleUiTableViewCell(frame: CGRect(x: 0,y: 0,width: contentView.frame.width,height: 80))
cell.setArticle(article: item,menuClickListener: { article in
self.clickListener(FollowingItemClick.ArticleMenuClick(article))
},contentClickListener: { article in
self.clickListener(FollowingItemClick.ArticleClick(article))
})
cell.backgroundColor = Colors.Card.background
return cell
} else if let item = item as? SearchPresentable {
let cell = SearchTableViewCell(frame: CGRect(x: 0,height: 80))
cell.setData(searchPresentable: item,menuClickListener: { searchPresentable in
self.clickListener(FollowingItemClick.SearchMenuClick(searchPresentable))
},contentClickListener: { searchPresentable in
self.clickListener(FollowingItemClick.SearchClick(searchPresentable))
})
cell.backgroundColor = Colors.Card.background
return cell
} else {
fatalError("No proper item type found for \(item)")
}
}
func setData(item: FollowingItem,width: CGFloat,clickListener: @escaping (FollowingItemClick) -> Void) {
widthAnchor.constraint(equalToConstant: width).isActive = true
contentView.widthAnchor.constraint(equalToConstant: width).isActive = true
self.clickListener = clickListener
self.item = item
if let item = item as? FollowingArticleItem {
items = item.items
} else if let item = item as? FollowingSearchItem {
items = item.items
}
tableView.reloadData()
title.text = item.title
viewMoreButton.setTitle(item.viewMoreText,for: .normal)
}
}
自动调整 TableView 大小
class SelfSizingTableView: UITableView {
override func reloadData() {
super.reloadData()
invalidateIntrinsicContentSize()
layoutIfNeeded()
}
override var contentSize: CGSize {
didSet {
invalidateIntrinsicContentSize()
}
}
override var intrinsicContentSize: CGSize {
layoutIfNeeded()
let height = contentSize.height
return CGSize(width: contentSize.width,height: height)
}
}
第一次打开标签时的屏幕截图。请注意,列表中还有更多文章(共 3 篇)。单元格似乎只首先显示屏幕视图。
导航到另一个选项卡时的屏幕截图,然后返回到这个选项卡。注意一切都变得疯狂。
解决方法
所以我注意到了。这是您在此处实现的一些复杂架构。我建议您仅使用表格视图设计此页面(如果仅垂直滚动,我们可以实现)。
但是让我们先解决这个问题,因为它是一个 tableView
位于单元格内部的复杂架构,在这种情况下,单元格不知道如何调整大小(因为涉及滚动)。因此,您必须从 func collectionView(collectionView: UICollectionView,layout collectionViewLayout: UICollectionViewLayout,sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
内部手动计算每个集合视图组件的大小。您可以通过编写一些函数来计算单元格中的行数并将其乘以大小来实现。
但又一次。我会建议只使用 tableView
和多个部分和单元格类型来制作这个 UI。
尝试实现 UITableViewDelegate 方法来返回行的高度。
func tableView(_ tableView: UITableView,heightForRowAt indexPath: IndexPath) -> CGFloat {
let item = items[indexPath.row]
if let item = item as? Something {
return 80 //Or whatever value it should be
} else {
return 0 //Or whatever value it should be
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。