我一直致力于一组允许UITableView
及其相关类使用自动布局和动态类型的类。它基于an answer on Stack Overflow,旨在添加自动布局支持。
到目前为止,它运行良好,但在使用大小类时我遇到了一些问题。第一个与计算高度的表直接相关:
当我创建新的UITableViewCell
但未将其添加到任何视图时,尺寸等级为Any
x Any
,所以当我有了根据尺寸等级更改的某些子视图或约束,它们始终像Any
x Any
情况一样工作。到目前为止,我非常讨厌的解决方案是创建一个新的UIWindow
,我将单元格添加到:{/ p>
UIWindow(frame: UIScreen.mainScreen().applicationFrame)
这项功能正常,但我遇到了一些问题:
UIWindow
对象是否有一种简单/更有效的方法可以确保UITableViewCell
知道其大小等级,而无需创建新的UIWindow
,或者更有效地执行此操作?也许我可以添加一个
大多数当前代码都可以通过GitHub page找到,但最相关的方法是:
DynamicTableViewController
private var cachedClassesForCellReuseIdentifiers = [String : UITableViewCell.Type]()
private var cachedNibsForCellReuseIdentifiers = [String : UINib]()
private var offscreenCellRowsForReuseIdentifiers = [String : UITableViewCell]()
private var offScreenWindow: UIWindow = {
return UIWindow(frame: UIScreen.mainScreen().applicationFrame)
}()
override public func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
// This method is called with an NSMutableIndexPath, which is not compatible with an imutable NSIndexPath,
// so we create an imutable NSIndexPath to be passed to the following methods
let imutableIndexPath = NSIndexPath(forRow: indexPath.row, inSection: indexPath.section)
if let reuseIdentifier = self.cellReuseIdentifierForIndexPath(imutableIndexPath) {
if let cell = self.cellForReuseIdentifier(reuseIdentifier) {
self.configureCell(cell, forIndexPath: indexPath)
if let dynamicCell = cell as? DynamicTableViewCell {
let height = dynamicCell.heightInTableView(tableView)
return height
} else {
// Fallback for non-DynamicTableViewCell cells
let size = cell.contentView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)
let cellBoundsHeight = CGRectGetHeight(cell.bounds)
if size.height > 0 && size.height >= cellBoundsHeight {
// +1 for the cell separator
return size.height + 1
} else {
// In some situations (such as the content view not having any/enough constraints to get a height), the
// size from the systemLayoutSizeFittingSize: will be 0. However, because this can _sometimes_ be intended
// (e.g., when adding to a default style; see: DynamicSubtitleTableViewCell), we just return
// the height of the cell as-is. This may make some cells look wrong, but overall will also prevent 0 being returned,
// hopefully stopping some things from breaking.
return cellBoundsHeight + 1
}
}
}
}
return UITableViewAutomaticDimension
}
private func cellForReuseIdentifier(reuseIdentifier: String) -> UITableViewCell? {
if self.offscreenCellRowsForReuseIdentifiers[reuseIdentifier] == nil {
if let cellClass = self.cachedClassesForCellReuseIdentifiers[reuseIdentifier] {
let cell = cellClass()
self.offScreenWindow.addSubview(cell)
self.offscreenCellRowsForReuseIdentifiers[reuseIdentifier] = cell
} else if let cellNib = self.cachedNibsForCellReuseIdentifiers[reuseIdentifier] {
if let cell = cellNib.instantiateWithOwner(nil, options: nil).first as? UITableViewCell {
self.offScreenWindow.addSubview(cell)
self.offscreenCellRowsForReuseIdentifiers[reuseIdentifier] = cell
}
}
}
return self.offscreenCellRowsForReuseIdentifiers[reuseIdentifier]
}
DynamicTableViewCell
public func heightInTableView(tableView: UITableView) -> CGFloat {
var height: CGFloat!
if self.calculateHeight {
self.setNeedsUpdateConstraints()
self.updateConstraintsIfNeeded()
self.bounds = CGRectMake(0, 0, CGRectGetWidth(tableView.bounds), CGRectGetHeight(self.bounds))
self.setNeedsLayout()
self.layoutIfNeeded()
let size = self.contentView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)
let boundsHeight = CGRectGetHeight(self.bounds)
if size.height > 0 && size.height >= boundsHeight {
// +1 for the cell separator
height = size.height + 1
} else {
// In some situations (such as the content view not having any/enough constraints to get a height), the
// size from the systemLayoutSizeFittingSize: will be 0. However, because this can _sometimes_ be intended
// (e.g., when adding to a default style; see: DynamicSubtitleTableViewCell), we just return
// the height of the cell as-is. This may make some cells look wrong, but overall will also prevent 0 being returned,
// hopefully stopping some things from breaking.
height = boundsHeight + 1
}
} else {
height = self.cellHeight
}
if height < self.minimumHeight && self.minimumHeight != nil {
return self.minimumHeight!
} else {
return height
}
}
此解决方案适用于iOS 7和8,未来的解决方案也应如此。此限制也删除了UITraitCollection
的使用,因此我没有沿着这条路走下去(我甚至不确定它是否有帮助)
答案 0 :(得分:0)
使用IOS 8和Autolayout您可以使用内容视图设置估计行高并为内部视图设置约束,以便根据其中的内容进行缩放。这是我的回答Which is the best approach among Autolayout or calculating the height using NSAttributedString, to implement dynamic height of an UITableViewCell?
更新:对于IOS7,您需要计算高度即将到达时您可以在
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath
委托方法
#define HEIGHT_FOR_ONE_LINE 15; //define it according to your fonts
#define HEIGHT_FOR_SINGLE_ROWCELL 32;
#pragma mark - Table view data source
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *textToView= [self.yourDataSourceArray objectAtIndex:indexPath.row];
CGFloat screenWidth=[[UIScreen mainScreen]bounds].size.width;
CGFloat characterPerPoint= 10;
CGFloat widthTaken= characterPerPoint * textToView.length;
NSInteger numberOfLines= ceil(widthTaken/screenWidth);
CGFloat height=numberOfLines* HEIGHT_FOR_ONE_LINE;
height = height + HEIGHT_FOR_SINGLE_ROWCELL;
return height;
}