【发布时间】:2016-03-14 00:39:44
【问题描述】:
我最近发布了一个关于带有自定义 UITableCells 的 UITableView 的问题,当单元格的子视图使用 AutoLayout 定位时,该问题不流畅。我得到一些 cmets 表明缺乏平滑度是由于单元格的复杂布局。虽然我同意单元格布局越复杂,tableView 必须进行更多计算才能获得单元格的高度,但我认为 10-12 UIView 和 UILabel 子视图不会导致我在滚动时看到的滞后量iPad。
所以为了进一步证明我的观点,我创建了一个 UIViewController 项目,其中包含一个 UITableView 子视图和自定义 UITableViewCells,它们的子类中只有 2 个标签。而且滚动仍然不是很流畅。从我的角度来看,这是你能得到的最基本的——所以如果 UITableView 在这种设计下仍然不能正常工作,我一定是遗漏了一些东西。
下面使用的estimatedRowHeight 110 与实际行高平均值非常接近。当我使用“用户界面检查器”并逐个查看每个单元格的高度时,它们的范围是 103 - 124。
请记住,当我将下面的代码切换为不使用estimatedRowHeight 和UITableViewAutomaticDimension 而是实现func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {,使用帧值计算高度时,UITableView 像黄油一样滚动.
应用截图(供参考)
App源代码(滚动不流畅)
// The custom `Quote` object that holds the
// properties for our data mdoel
class Quote {
var text: String!
var author: String!
init(text: String, author: String) {
self.text = text
self.author = author
}
}
// Custom UITableView Cell, using AutoLayout to
// position both a "labelText" (the quote itself)
// and "labelAuthor" (the author's name) label
class CellQuote: UITableViewCell {
private var containerView: UIView!
private var labelText: UILabel!
private var labelAuthor: UILabel!
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
contentView.backgroundColor = UIColor.whiteColor()
containerView = UIView()
containerView.backgroundColor = UIColor(
red: 237/255,
green: 237/255,
blue: 237/255,
alpha: 1.0
)
contentView.addSubview(containerView)
containerView.translatesAutoresizingMaskIntoConstraints = false
containerView.leadingAnchor.constraintEqualToAnchor(contentView.leadingAnchor, constant: 0).active = true
containerView.trailingAnchor.constraintEqualToAnchor(contentView.trailingAnchor, constant: 0).active = true
containerView.topAnchor.constraintEqualToAnchor(contentView.topAnchor, constant: 4).active = true
containerView.bottomAnchor.constraintEqualToAnchor(contentView.bottomAnchor, constant: 0).active = true
labelText = UILabel()
labelText.numberOfLines = 0
labelText.font = UIFont.systemFontOfSize(18)
labelText.textColor = UIColor.darkGrayColor()
containerView.addSubview(labelText)
labelText.translatesAutoresizingMaskIntoConstraints = false
labelText.leadingAnchor.constraintEqualToAnchor(containerView.leadingAnchor, constant: 20).active = true
labelText.topAnchor.constraintEqualToAnchor(containerView.topAnchor, constant: 20).active = true
labelText.trailingAnchor.constraintEqualToAnchor(containerView.trailingAnchor, constant: -20).active = true
labelAuthor = UILabel()
labelAuthor.numberOfLines = 0
labelAuthor.font = UIFont.boldSystemFontOfSize(18)
labelAuthor.textColor = UIColor.blackColor()
containerView.addSubview(labelAuthor)
labelAuthor.translatesAutoresizingMaskIntoConstraints = false
labelAuthor.topAnchor.constraintEqualToAnchor(labelText.bottomAnchor, constant: 20).active = true
labelAuthor.leadingAnchor.constraintEqualToAnchor(containerView.leadingAnchor, constant: 20).active = true
labelAuthor.trailingAnchor.constraintEqualToAnchor(containerView.trailingAnchor, constant: -20).active = true
labelAuthor.bottomAnchor.constraintEqualToAnchor(containerView.bottomAnchor, constant: -20).active = true
self.selectionStyle = UITableViewCellSelectionStyle.None
}
func configureWithData(quote: Quote) {
labelText.text = quote.text
labelAuthor.text = quote.author
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
// The UIViewController that is a
class ViewController: UIViewController, UITableViewDataSource {
var tableView: UITableView!
var dataItems: [Quote]!
override func viewDidLoad() {
super.viewDidLoad()
tableView = UITableView()
tableView.dataSource = self
tableView.registerClass(CellQuote.self, forCellReuseIdentifier: "cellQuoteId")
tableView.backgroundColor = UIColor.whiteColor()
tableView.separatorStyle = UITableViewCellSeparatorStyle.None
tableView.estimatedRowHeight = 110
tableView.rowHeight = UITableViewAutomaticDimension
view.addSubview(tableView)
tableView.translatesAutoresizingMaskIntoConstraints = false
tableView.leadingAnchor.constraintEqualToAnchor(view.leadingAnchor).active = true
tableView.topAnchor.constraintEqualToAnchor(view.topAnchor, constant: 20).active = true
tableView.trailingAnchor.constraintEqualToAnchor(view.trailingAnchor).active = true
tableView.bottomAnchor.constraintEqualToAnchor(view.bottomAnchor).active = true
dataItems = [
Quote(text: "One kernel is felt in a hogshead; one drop of water helps to swell the ocean; a spark of fire helps to give light to the world. None are too small, too feeble, too poor to be of service. Think of this and act.", author: "Michael.Frederick"),
Quote(text: "A timid person is frightened before a danger, a coward during the time, and a courageous person afterward.", author: "Lorem.Approbantibus."),
Quote(text: "There is only one way to defeat the enemy, and that is to write as well as one can. The best argument is an undeniably good book.", author: "Lorem.Fruitur."),
// ... many more quotes ...
]
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
// MARK: - UITableViewDataSource
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dataItems.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cellQuoteId") as! CellQuote
cell.configureWithData(dataItems[indexPath.row])
return cell
}
}
我喜欢下面马特的建议,但我仍在尝试对其进行调整以适合我:
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
var cellHeights: [CGFloat] = [CGFloat]()
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if cellHeights.count == 0 {
var cellHeights = [CGFloat]()
let numQuotes: Int = dataItems.count
for index in 0...numQuotes - 1 {
let cell = CellQuote()
let quote = dataItems[index]
cell.configureWithData(quote)
let size = cell.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)
cellHeights.append(size.height)
}
self.cellHeights = cellHeights
}
return self.cellHeights[indexPath.row]
}
}
【问题讨论】:
标签: ios swift autolayout uitableview