Sha*_*man 104 uitableview ios uicollectionview
我们的一个应用程序屏幕要求我们放置UICollectionView一个UITableViewCell.这UICollectionView将具有动态数量的项目,从而产生必须动态计算的高度.但是,我在尝试计算嵌入式高度时遇到了问题UICollectionView.
我们的总体设计UIViewController是在故事板中创建的,并且确实利用了自动布局.但是,我不知道如何动态增加UITableViewCell基于高度的高度UICollectionView.
任何人都可以提供一些如何实现这一目标的建议或建议吗?
Pab*_*meu 111
正确的答案是YES,你CAN做到这一点.
我几周前遇到过这个问题.它实际上比你想象的要容易.将您的单元格放入NIB(或故事板)并固定它们,让自动布局完成所有工作
鉴于以下结构:
的TableView
TableViewCell
的CollectionView
CollectionViewCell
CollectionViewCell
CollectionViewCell
[...可变数量的细胞或不同的细胞大小]
解决方案是告诉自动布局首先计算collectionViewCell大小,然后集合视图contentSize,并将其用作单元格的大小.这是"做神奇" 的UIView方法:
-(void)systemLayoutSizeFittingSize:(CGSize)targetSize
withHorizontalFittingPriority:(UILayoutPriority)horizontalFittingPriority
verticalFittingPriority:(UILayoutPriority)verticalFittingPriority
Run Code Online (Sandbox Code Playgroud)
你必须在这里设置TableViewCell的大小,在你的情况下是CollectionView的contentSize.
在CollectionViewCell中,每次更改模型时都必须告诉单元格布局(例如:您使用文本设置UILabel,然后单元格必须再次布局).
- (void)bindWithModel:(id)model {
// Do whatever you may need to bind with your data and
// tell the collection view cell's contentView to resize
[self.contentView setNeedsLayout];
}
// Other stuff here...
Run Code Online (Sandbox Code Playgroud)
该TableViewCell确实神奇.它有一个出口,以您的的CollectionView,能够使用的CollectionView细胞自动布局estimatedItemSize的的UICollectionViewFlowLayout.
然后,诀窍是在systemLayoutSizeFittingSize ...方法中设置tableView单元格的大小.(注意:iOS8或更高版本)
注:我试图用的tableView的代表单元的高度方法-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath.但为时已晚的自动布局系统来计算的CollectionView contentSize,有时你可能会发现错误调整细胞.
@implementation TableCell
- (void)awakeFromNib {
[super awakeFromNib];
UICollectionViewFlowLayout *flow = (UICollectionViewFlowLayout *)self.collectionView.collectionViewLayout;
// Configure the collectionView
flow.minimumInteritemSpacing = ...;
// This enables the magic of auto layout.
// Setting estimatedItemSize different to CGSizeZero
// on flow Layout enables auto layout for collectionView cells.
// https://developer.apple.com/videos/play/wwdc2014-226/
flow.estimatedItemSize = CGSizeMake(1, 1);
// Disable the scroll on your collection view
// to avoid running into multiple scroll issues.
[self.collectionView setScrollEnabled:NO];
}
- (void)bindWithModel:(id)model {
// Do your stuff here to configure the tableViewCell
// Tell the cell to redraw its contentView
[self.contentView layoutIfNeeded];
}
// THIS IS THE MOST IMPORTANT METHOD
//
// This method tells the auto layout
// You cannot calculate the collectionView content size in any other place,
// because you run into race condition issues.
// NOTE: Works for iOS 8 or later
- (CGSize)systemLayoutSizeFittingSize:(CGSize)targetSize withHorizontalFittingPriority:(UILayoutPriority)horizontalFittingPriority verticalFittingPriority:(UILayoutPriority)verticalFittingPriority {
// With autolayout enabled on collection view's cells we need to force a collection view relayout with the shown size (width)
self.collectionView.frame = CGRectMake(0, 0, targetSize.width, MAXFLOAT);
[self.collectionView layoutIfNeeded];
// If the cell's size has to be exactly the content
// Size of the collection View, just return the
// collectionViewLayout's collectionViewContentSize.
return [self.collectionView.collectionViewLayout collectionViewContentSize];
}
// Other stuff here...
@end
Run Code Online (Sandbox Code Playgroud)
请记住在TableViewController上为tableView单元格启用自动布局系统:
- (void)viewDidLoad {
[super viewDidLoad];
// Enable automatic row auto layout calculations
self.tableView.rowHeight = UITableViewAutomaticDimension;
// Set the estimatedRowHeight to a non-0 value to enable auto layout.
self.tableView.estimatedRowHeight = 10;
}
Run Code Online (Sandbox Code Playgroud)
信用:@rbarbera帮助解决了这个问题
Igo*_*gor 84
我认为,我的方式更简单,然后由@PabloRomeu提出.
步骤1.创建出口UICollectionView到UITableViewCell subclass,其中UICollectionView被放置.让,它的名字将是collectionView
步骤2.在IB中添加UICollectionView高度约束并创建出口UITableViewCell subclass.让,它的名字将是collectionViewHeight.
第3步.tableView:cellForRowAtIndexPath:添加代码:
// deque a cell
cell.frame = tableView.bounds;
[cell layoutIfNeeded];
[cell.collectionView reloadData];
cell.collectionViewHeight.constant = cell.collectionView.collectionViewLayout.collectionViewContentSize.height;
Run Code Online (Sandbox Code Playgroud)
Riv*_*era 21
表视图和集合视图都是UIScrollView子类,因此不希望嵌入到另一个滚动视图中,因为它们尝试计算内容大小,重用单元格等.
我建议您仅使用集合视图来实现所有目的.
您可以将其划分为多个部分,并将某些部分的布局"视为"视图,将其他部分视为集合视图.毕竟,使用表视图的集合视图无法实现任何功能.
如果您的集合视图"部件"具有基本网格布局,则还可以使用常规表格单元格来处理它们.如果你不需要iOS 5支持,你应该更好地使用集合视图.
小智 9
我通读了所有的答案。这似乎适用于所有情况。
override func systemLayoutSizeFitting(_ targetSize: CGSize, withHorizontalFittingPriority horizontalFittingPriority: UILayoutPriority, verticalFittingPriority: UILayoutPriority) -> CGSize {
collectionView.layoutIfNeeded()
collectionView.frame = CGRect(x: 0, y: 0, width: targetSize.width , height: 1)
return collectionView.collectionViewLayout.collectionViewContentSize
}
Run Code Online (Sandbox Code Playgroud)
小智 7
帕勃罗·罗梅(Pablo Romeu)的上述回答(/sf/answers/2335486471/)对我的问题有极大帮助。但是,我必须做一些不同的事情才能使它解决我的问题。首先,我不必layoutIfNeeded()经常打电话。我只需要collectionView在systemLayoutSizeFitting函数中调用它。
其次,我在表格视图单元格中的集合视图上具有自动布局约束,以对其进行填充。因此,targetSize.width在设置collectionView.frame的宽度时,我不得不从减去前导和尾随页边距。我还必须将顶部和底部边距添加到返回值的CGSize高度。
为了获得这些约束常量,我可以选择为约束创建出口,对它们的常量进行硬编码,或者通过标识符查找它们。我决定选择第三个选项,以使自定义表格视图单元格类易于重用。最后,这就是我需要使其工作的一切:
class CollectionTableViewCell: UITableViewCell {
// MARK: -
// MARK: Properties
@IBOutlet weak var collectionView: UICollectionView! {
didSet {
collectionViewLayout?.estimatedItemSize = CGSize(width: 1, height: 1)
selectionStyle = .none
}
}
var collectionViewLayout: UICollectionViewFlowLayout? {
return collectionView.collectionViewLayout as? UICollectionViewFlowLayout
}
// MARK: -
// MARK: UIView functions
override func systemLayoutSizeFitting(_ targetSize: CGSize, withHorizontalFittingPriority horizontalFittingPriority: UILayoutPriority, verticalFittingPriority: UILayoutPriority) -> CGSize {
collectionView.layoutIfNeeded()
let topConstraintConstant = contentView.constraint(byIdentifier: "topAnchor")?.constant ?? 0
let bottomConstraintConstant = contentView.constraint(byIdentifier: "bottomAnchor")?.constant ?? 0
let trailingConstraintConstant = contentView.constraint(byIdentifier: "trailingAnchor")?.constant ?? 0
let leadingConstraintConstant = contentView.constraint(byIdentifier: "leadingAnchor")?.constant ?? 0
collectionView.frame = CGRect(x: 0, y: 0, width: targetSize.width - trailingConstraintConstant - leadingConstraintConstant, height: 1)
let size = collectionView.collectionViewLayout.collectionViewContentSize
let newSize = CGSize(width: size.width, height: size.height + topConstraintConstant + bottomConstraintConstant)
return newSize
}
}
Run Code Online (Sandbox Code Playgroud)
作为通过标识符检索约束的帮助函数,我添加了以下扩展名:
extension UIView {
func constraint(byIdentifier identifier: String) -> NSLayoutConstraint? {
return constraints.first(where: { $0.identifier == identifier })
}
}
Run Code Online (Sandbox Code Playgroud)
注意:您将需要在情节提要中或在创建约束的任何位置设置标识符。除非它们的常数为0,否则没关系。同样,如Pablo的回复一样,您将需要将其UICollectionViewFlowLayout用作收藏视图的布局。最后,确保将collectionViewIBOutlet 链接到情节提要。
通过上面的自定义表格视图单元格,我现在可以在需要收集视图并使其实现UICollectionViewDelegateFlowLayout和UICollectionViewDataSource协议的任何其他表格视图单元格中将其子类化。希望这对其他人有帮助!
我会在集合视图类上放置一个静态方法,该方法将根据其所拥有的内容返回一个大小。然后使用该方法返回heightForRowAtIndexPath正确的大小。
另请注意,当您嵌入这些类型的 viewController 时,您可能会遇到一些奇怪的行为。我做过一次,但遇到了一些奇怪的记忆问题,但从未解决过。
| 归档时间: |
|
| 查看次数: |
44534 次 |
| 最近记录: |