ios - 在tableview单元格内创建动态collectionView
问题描述
我正在尝试在 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 大小。
解决方案
如果我正确理解您的问题,那么您在 UITableView 中有不止一行具有水平 UICollectionViews。这些集合视图具有基于其中的图像具有动态大小的单元格。
所以 UITableView 的宽度是固定的,但是行的高度取决于 UICollectionView 的高度,对吗?
我建议在 UITableView 中使用自定大小的单元格。请参阅此处的参考: https ://developer.apple.com/library/archive/documentation/UserExperience/Conceptual/AutolayoutPG/WorkingwithSelf-SizingTableViewCells.html
之后,你需要找到一种方法来正确计算 UICollectionView 的高度,这样 UITableView 单元格才能确定正确的高度。有几种方法可以做到这一点,例如通过覆盖intrinsicContentSize
UICollectionView 的属性并返回图像的最大高度。
推荐阅读
- swift - sqlite3 打开错误(macOS、swift5、Xcode 11.3.1)
- snowflake-cloud-data-platform - n 行的随机样本
- xamarin - XamarinUITest 将参数传递给 AndroidAppConfigurator
- python - 从列表的字典制作列表列表的字典
- angular - 动态 API 网址
- algorithm - 为什么贪心算法是启发式的,而不是元启发式的?
- assembly - 汇编中的内存at和ptr之间的区别
- java - 使用criteriaquery fetch 和createcriteria.setFechMode 的区别
- python - 在 pandas.Dataframe 中查找 NaN
- pandas - 如何从频率表创建箱线图