如何根据具有打字机效果的UILabel设置单元格的高度
我在UITableView的单元格中有一个UILabel。
要根据标签的高度来调整单元格的高度,没关系,它可以很好地工作。
但是我需要添加另一个约束。 我需要用打字机效果(逐字母)显示UILabel。
我的扩展效果很好:
extension UILabel{ func setTextWithTypeAnimation(id:String, typedText: String, pauseCharacterArray: [Int:Double], characterInterval: TimeInterval = 0.06 ) { text = "" let group = DispatchGroup() group.enter() DispatchQueue.global(qos: .userInteractive).async { for (index, character) in typedText.characters.enumerated() { DispatchQueue.main.async { self.text = self.text! + String(character) } Thread.sleep(forTimeInterval: characterInterval) } group.leave() } group.notify(queue: .main) { //do something } }
我试图在我的configureCell基金中调用这个函数:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "ParagraphTableViewCell", for: indexPath) as! ParagraphTableViewCell cell.delegate = self self.configureCell(cell: cell, atIndexPath: indexPath) return cell } func configureCell(cell: ParagraphTableViewCell, atIndexPath indexPath: IndexPath) { let paragraph = paragraphArray[indexPath.row] as! Paragraph let pauseCharactersArray:[Int:Double] = [1:0, 6:0] cell.dialogueLabel.setTextWithTypeAnimation(id:"intro", typedText: "lorem ipsum", pauseCharacterArray: pauseCharactersArray) }
但标签不出现。 我认为这是因为单元格中标签的高度设置为0,并且从不更新。
我不知道如何调整“实时”单元的高度(每次显示一个字符)
编辑
我使用自动布局
编辑2
打字机效果,运行在一个简单的UILabel没有UITableView:
在xib中设置的单元格:
当我运行时,UILabel不会出现:
我能够实现使用不同的方法。
- 我创build了一个堆栈视图来分组标签和button(和一个子堆栈视图排列你的button)。
- 在button的堆栈视图中,我通过IB固定了高度。
- 在父堆栈视图上。 我把堆栈视图固定到单元格的边缘。
- 在标签上,我固定两边,以适应堆栈视图(不要钉在底部的一面,你可以自由钉住顶部)
这是我的IB屏幕截图作为参考。
-
在您的ViewController上,设置以下属性:
yourTableView.rowHeight = UITableViewAutomaticDimension yourTableView.rowHeight.estimatedRowHeight = 40 // You should set an initial estimated row height here, the number 40 was chosen arbitrarily
-
我编辑你的方法来添加一个callback。
func setTextWithTypeAnimation(id:String, typedText: String, pauseCharacterArray: [Int:Double], characterInterval: TimeInterval = 0.06, callBackAfterCharacterInsertion:(()->())?) { text = "" let group = DispatchGroup() group.enter() DispatchQueue.global(qos: .userInteractive).async { for (_, character) in typedText.characters.enumerated() { DispatchQueue.main.async { self.text = self.text! + String(character) callBackAfterCharacterInsertion?() } Thread.sleep(forTimeInterval: characterInterval) } group.leave() } group.notify(queue: .main) { //do something } }
-
通过callback,在每次更新字符后,我
beginUpdates()
从TableView中endUpdates()
beginUpdates()
和endUpdates()
。
希望以任何方式帮助你。
我find了一个解决scheme,但我不知道它是否非常干净。
我在configureCell方法中添加了layoutIfNeeded():
func configureCell(cell: ParagraphTableViewCell, atIndexPath indexPath: IndexPath) { let paragraph = paragraphArray[indexPath.row] as! Paragraph cell.layoutIfNeeded() let pauseCharactersArray:[Int:Double] = [1:0, 6:0] cell.dialogueLabel.setTextWithTypeAnimation(id:"intro", typedText: "lorem ipsum", pauseCharacterArray: pauseCharactersArray)
}
我在我的控制器中添加了heightForRowAtIndexPath方法,它返回我的标签的高度:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { let cell = tableView.dequeueReusableCell(withIdentifier: "ParagraphTableViewCell") as! ParagraphTableViewCell return cell.dialogueLabel.frame.height }
它的工作原理,但我不明白为什么,因为在heightForRowAtIndexPath我返回标签的高度,而不是单元格的高度。
如果有人有更好的解决scheme,我很感兴趣。
你这样做的方式需要一点重构:你需要在你的TypeWriter函数中引用tableView。 无论如何,一个快速和肮脏的修复如下:
首先在你的单元格中添加一个对tableView的弱引用:
class ParagraphTableViewCell: UITableViewCell { weak var tableView: UITableView? [...] }
然后你去你的主循环寻找它,告诉tableView你正在更新的东西:
DispatchQueue.main.async { if let delegate = (self.superview?.superview as? ParagraphTableViewCell)?.tableView { delegate.beginUpdates() self.text = self.text! + String(character) delegate.endUpdates() } }
我不会build议在应用程序中使用这种方法,并且您肯定希望将其重构为更稳定的模式,我的示例显示了它如何与您的代码一起工作。
我已经创build了一个可用的示例来testing我的代码,请在此处将其打包