在tableview单元格内创建动态collectionView
Posted
技术标签:
【中文标题】在tableview单元格内创建动态collectionView【英文标题】:Create dynamic collectionView inside tableview cell 【发布时间】:2020-03-03 20:07:02 【问题描述】:我正在尝试在 tableviewcell 内创建一个水平集合视图,其中包含一个动态大小的 uiimageview,这将是强制视图。
我创建了一个 UIView :
public class CardImage: UIView
private var imageView: UIImageView?
private var titleLabel: UILabel?
private var descriptionLabel: UILabel?
private var subtitleLabel: UILabel?
private var icon: UIImage?
private var imageURL: String?
private var screenPercentage: CGFloat = 1.0
override public func layoutSubviews()
super.layoutSubviews()
layer.cornerRadius = 4
public override func awakeFromNib()
super.awakeFromNib()
setup()
layoutSubviews()
public init()
super.init(frame: .zero)
setup()
layoutSubviews()
required init?(coder aDecoder: NSCoder)
super.init(coder: aDecoder)
setup()
layoutSubviews()
public func fill(dto: SomeDTO)
setupImage(icon: dto.image, imageUrl: dto.imageURL)
descriptionLabel?.text = dto.description
titleLabel?.text = dto.title
subtitleLabel?.text = dto.subtitle
screenPercentage = dto.screenPercentage
private func setup()
isUserInteractionEnabled = true
translatesAutoresizingMaskIntoConstraints = false
backgroundColor = .red
titleLabel = UILabel()
titleLabel?.textColor = .white
titleLabel?.numberOfLines = 1
addSubview(titleLabel!)
descriptionLabel = UILabel()
descriptionLabel?.textColor = .white
descriptionLabel?.numberOfLines = 2
addSubview(descriptionLabel!)
subtitleLabel = UILabel()
subtitleLabel?.textColor = .white
subtitleLabel?.numberOfLines = 1
addSubview(subtitleLabel!)
imageView = UIImageView(frame: .zero)
imageView?.backgroundColor = .red
addSubview(imageView!)
setupConstraints()
private func setupImage(icon: UIImage?, imageUrl: String?)
if let url = imageURL
return
guard let image = icon else
return
imageView?.image = image
imageView?.contentMode = .scaleAspectFit
setNeedsDisplay()
setNeedsLayout()
private func setupConstraints()
imageView?.translatesAutoresizingMaskIntoConstraints = false
imageView?.topAnchor.constraint(equalTo: topAnchor).isActive = true
imageView?.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
imageView?.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true
let screenSize = UIScreen.main.bounds
let computedWidth = screenSize.width * screenPercentage
imageView?.widthAnchor.constraint(equalToConstant: computedWidth).isActive = true
//the image should be 16:9
imageView?.heightAnchor.constraint(equalTo: widthAnchor, multiplier: 9.0/16.0).isActive = true
titleLabel?.translatesAutoresizingMaskIntoConstraints = false
titleLabel?.topAnchor.constraint(equalTo: imageView!.bottomAnchor, constant: 16).isActive = true
titleLabel?.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 16).isActive = true
titleLabel?.heightAnchor.constraint(equalToConstant: 18).isActive = true
subtitleLabel?.translatesAutoresizingMaskIntoConstraints = false
subtitleLabel?.topAnchor.constraint(equalTo: titleLabel!.topAnchor).isActive = true
subtitleLabel?.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -16).isActive = true
titleLabel?.widthAnchor.constraint(equalTo: subtitleLabel!.widthAnchor).isActive = true
titleLabel?.trailingAnchor.constraint(equalTo: subtitleLabel!.leadingAnchor, constant: 6).isActive = true
descriptionLabel?.translatesAutoresizingMaskIntoConstraints = false
descriptionLabel?.topAnchor.constraint(equalTo: titleLabel!.bottomAnchor, constant: 16).isActive = true
descriptionLabel?.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 16).isActive = true
descriptionLabel?.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -16).isActive = true
descriptionLabel?.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -16).isActive = true
将在 CollectionViewCell 内:
public class CardImageCollectionViewCell: UICollectionViewCell
private let view: CardImage = CardImage()
override public func awakeFromNib()
super.awakeFromNib()
translatesAutoresizingMaskIntoConstraints = false
//this only pin the view to the four anchors of the uicollectionview
view.pinToBounds(of: self.contentView)
backgroundColor = .clear
AccessibilityManager.setup(self, log: true)
public func fill(dto: SomeDTO)
view.fill(dto: dto)
然后是 CollectionViewCell,在一个 tableviewcell 内,它有一个 collectionview:
public class CardImageCollectionView: UIView, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout
@IBOutlet private weak var collectionView: UICollectionView!
private var dto: [SomeDTO] = []
public override func awakeFromNib()
super.awakeFromNib()
setup()
private func setup()
backgroundColor = .blue
collectionView.backgroundColor = .clear
collectionView.delegate = self
collectionView.dataSource = self
if let flowLayout = collectionView?.collectionViewLayout as? UICollectionViewFlowLayout
flowLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
registerCells()
func fill(dto: [SomaImageCardDTO])
self.dto = dto
DispatchQueue.main.async
self.collectionView.reloadData()
self.collectionView.layoutIfNeeded()
private func registerCells()
collectionView.register(UINib(nibName: String(describing: CardImageCollectionViewCell.self), bundle: nil), forCellWithReuseIdentifier: String(describing: CardImageCollectionViewCell.self))
public func numberOfSections(in collectionView: UICollectionView) -> Int
return 1
public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
return dto.count
//this should not be setted since the sizing is automatic
// public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
// return CGSize(width: 304, height: 238)
//
//
public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: String(describing: CardImageCollectionViewCell.self), for: indexPath) as! CardImageCollectionViewCell
cell.fill(dto: dto[indexPath.row])
return cell
我面临的两个问题是,图像不能假定任何大小,因为集合视图在填充一些信息之前没有任何大小。
然后,即使我设置了图像大小,我也无法将信息传递给 UITableViewcell 大小。
【问题讨论】:
【参考方案1】:如果我正确理解您的问题,您在 UITableView 中有不止一行具有水平 UICollectionViews。这些集合视图的单元格根据其中的图像具有动态大小。
所以 UITableView 的宽度是固定的,但是行的高度取决于 UICollectionView 的高度,对吗?
我建议在 UITableView 中使用自定大小的单元格。请参阅此处的参考: https://developer.apple.com/library/archive/documentation/UserExperience/Conceptual/AutolayoutPG/WorkingwithSelf-SizingTableViewCells.html
之后,你需要找到一种方法来正确计算 UICollectionView 的高度,这样 UITableView 单元格才能确定正确的高度。有几种方法可以做到这一点,例如通过覆盖 UICollectionView 的 intrinsicContentSize
属性并返回图像的最大高度。
【讨论】:
以上是关于在tableview单元格内创建动态collectionView的主要内容,如果未能解决你的问题,请参考以下文章
在单元格内编辑textview时,将另一个单元格添加到tableview
完成在单元格内编辑 textview 后向 tableview 添加另一个单元格
UITableView 上的水平滚动正在改变 UIPageControl 的位置,该 UIPageControl 附加到 TableView 单元格内的滚动视图
UItableview 单元格的动态高度与 UItableview 单元格内的 UItableview