最近,我正在尝试做一些练习项目。所以我看了“开发iOS应用程序”课程,斯坦福大学,CS193P,2017。
现在,我正在做“Smashtag”项目,但我遇到了一些问题。 我想使用带有两个UICollectionViewFlowLayout的CollectionView,通过SegmentedControl在每个xib中显示两个类型(一个像tableView,另一个在方块中显示图像)。
我的问题如下:
- 醇>
如何使CollectionViewCell显示在动态高度,就像TableView的UITableViewAutomaticDimension一样?
这就是我刚才尝试的内容:
我尝试使用 UICollectionViewFlowLayoutAutomaticSize将CollectionView的autoResize设置与TableView的autoDimension一样。 (@available(iOS 10.0,*))
enum CollectionViewType {
case tweet
case image
}
// MARK: - Decide What Kind Of FlowLayout
func decideFlowLayout(type: CollectionViewType) -> UICollectionViewFlowLayout {
// just for .image type
var howManyImageShowing = 3
var imageShowingWidth: Double {
return Double(self.view.frame.width) / Double(howManyImageShowing)
}
// .tweet is a type showing like TableViewCell -> this make me confused !!
// another type is just showing a image in square -> I have no problem here
let estimatedItemSize = type == .tweet ? CGSize(width: self.view.frame.width, height: 155.0) :
CGSize(width: imageShowingWidth, height: imageShowingWidth)
let collectionViewLayout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
collectionViewLayout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
// --------- Make this setting as TableView does ---------
// ------------ Somethis just like this below ------------
/*
tableView.estimatedRowHeight = 155.0
tableView.rowHeight = UITableViewAutomaticDimension
*/
collectionViewLayout.estimatedItemSize = estimatedItemSize
collectionViewLayout.itemSize = UICollectionViewFlowLayoutAutomaticSize
// -------------------------------------------------------
collectionViewLayout.minimumLineSpacing = 0
collectionViewLayout.minimumInteritemSpacing = 0
return collectionViewLayout
}
我的CollectionViewCell xib的约束: 但是当我运行这个应用程序时它有错误
- 醇>
为什么这个解决方案会起作用?
我已经在Stack Overflow中搜索了这个问题的这么多解决方案,但我发现这个并让我真的很困惑:(
此解决方案为视图提供了一个 宽度约束 ,它位于CollectionViewCell xib中,并将此约束的常量设置为值,它可以正常工作!我无法配置为什么 宽度约束 会使单元格的高度处于动态状态?这让我很困惑,我觉得这很奇怪......
class Cell: UICollectionViewCell {
@IBOutlet weak var headerLabel: UILabel!
@IBOutlet weak var descriptionLabel: UILabel!
@IBOutlet weak var widthConstraint: NSLayoutConstraint!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
self.contentView.translatesAutoresizingMaskIntoConstraints = false
let screenWidth = UIScreen.main.bounds.size.width
widthConstraint.constant = screenWidth - (2 * 12)
}
}
- 醇>
如何在不使用 UICollectionViewFlowLayoutAutomaticSize的情况下进行CollectionViewCell动态高度。 (@available(iOS 10.0,*)) ?
因为我不仅要在iOS 10中处理不同的iOS版本,还要在iOS 10以下处理。
我真的想成为iOS开发专业人士和优秀的开发人员,但我还在学习和尝试。任何回复我将不胜感激。
谢谢!
答案 0 :(得分:5)
使用以下代码根据显示的文字更改高度:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
return CGSizeMake(view.frame.width , 64)
}
override func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
{
let approximateWidthOfContent = view.frame.width - x
// x is the width of the logo in the left
let size = CGSize(width: approximateWidthOfContent, height: 1000)
//1000 is the large arbitrary values which should be taken in case of very high amount of content
let attributes = [NSFontAttributeName: UIFont.systemFont(ofSize: 15)]
let estimatedFrame = NSString(string: user.bioText).boundingRect(with: size, options: .usesLineFragmentOrigin, attributes: attributes, context: nil)
return CGSize(width: view.frame.width, height: estimatedFrame.height + 66)
}
答案 1 :(得分:3)
我解决了它:)
我只是尝试计算我的单元格的宽度,并期望sizeForItemAt函数的高度,它可以工作!
以下代码:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let imageShowingWidth: CGFloat = self.view.frame.width / CGFloat(self.howManyImageShowing)
let labelName = "@\(self.tweetShowing[indexPath.row].user.screenName) (\(self.tweetShowing[indexPath.row].user.name))"
let labelNameFont: UIFont = UIFont(name: "PingFangTC-Semibold", size: 16)!
let labelNameWidth: CGFloat = self.view.frame.width - YourWidthOffSet// (YourWidthOffSet include all images' width and all margins)
let labelNameHeight: CGFloat = self.getHeightForLable(labelWidth: labelNameWidth, labelText: labelName, labelFont: labelNameFont)
let labelContentFont: UIFont = UIFont(name: "PingFangTC-Regular", size: 16)!
let labelContentHeight: CGFloat = self.getHeightForLable(labelWidth: labelNameWidth, numberOfLines: 0, labelText: self.tweetShowing[indexPath.row].text, labelFont: labelContentFont)
let cellHeight: CGFloat = labelNameHeight + labelContentHeight + YourHeightOffSet // (YourHeightOffSet means all margins)
return self.typeControl.selectedSegmentIndex == 0 ? CGSize(width: self.view.frame.width, height: cellHeight) : CGSize(width: imageShowingWidth, height: imageShowingWidth)
}
func getHeightForLable(labelWidth: CGFloat, numberOfLines: Int = 1, labelText: String, labelFont: UIFont) -> CGFloat {
let tempLabel: UILabel = UILabel(frame: CGRect(x: 0, y: 0, width: labelWidth, height: CGFloat.greatestFiniteMagnitude))
tempLabel.numberOfLines = numberOfLines
tempLabel.text = labelText
tempLabel.font = labelFont
tempLabel.sizeToFit()
return tempLabel.frame.height
}
答案 2 :(得分:1)
您需要做的就是为UICollectionView布局制作IBOutlet,
将estimatedItemSize
设置为任意大小,
在您的单元格类中,您必须指定单元格宽度(如果您只想要高度为动态且宽度为静态)和/或awakeFromNib
中的高度,并禁用translatesAutoresizingMaskIntoConstraints self.contentView.translatesAutoresizingMaskIntoConstraints = false
。
所以最终结果应该是这样的
class ProfileViewController: UIViewController {
@IBOutlet var collectionView: UICollectionView!
@IBOutlet var collectionLayout: UICollectionViewFlowLayout!
var person: Person!
override func viewDidLoad() {
super.viewDidLoad()
collectionView.register(UINib(nibName: "ProfileCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "Cell")
collectionLayout.estimatedItemSize = CGSize(width: screenWidth * 0.4, height: 1)
collectionView.reloadData()
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! ProfileCollectionViewCell
return cell
}
}
你的细胞类应该是这样的
class ProfileCollectionViewCell: UICollectionViewCell {
@IBOutlet var containerWidthConstraint: NSLayoutConstraint!
override func awakeFromNib() {
super.awakeFromNib()
self.contentView.translatesAutoresizingMaskIntoConstraints = false
containerWidthConstraint.constant = screenWidth - (2 * 12)
}
}
这是ios中自我调整大小的好教程 https://engineering.shopspring.com/dynamic-cell-sizing-in-uicollectionview-fd95f614ef80
答案 3 :(得分:0)
将
estimatedSize
提供给您的UICollectionViewLayout
。估计的大小应该是xib大小检查器中显示的大小。
collectionViewLayout.estimatedItemSize = CGSize(width: collectionView.frame.width, height: 50)
在您的
preferredLayoutAttributesFitting(_:)
中覆盖方法UICollectionViewCell
override func preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes {
setNeedsLayout()
layoutIfNeeded()
let size = contentView.systemLayoutSizeFitting(layoutAttributes.size)
var frame = layoutAttributes.frame
frame.size.height = ceil(size.height)
layoutAttributes.frame = frame
return layoutAttributes
}
您的收藏夹视图单元格现在将根据内容具有动态大小。