我正在尝试使用自定义动画为选择状态和突出显示状态编写UITableViewCell
编码。我已经覆盖了setSelected:animated:
和setHighlighted:animated:
方法。但是,这两个方法总是用animated:false
来调用。因此,我无法确定系统是在调用方法(在表视图清除选择时)还是在用户点击时。现在,对于高亮显示,我可能只是假定它总是由用户调用,因为我没有找到其他任何仅以编程方式高亮显示单元格的方法。对于setSelected:animated:
,我必须知道是否要设置动画。起初,我在点击单元格时一开始找不到正在调用setSelected:animated:
的内容,因为即使在覆盖每个UITableViewDelegate
方法而未调用super
,setSelected:animated:
的情况下,从某个地方接到电话。
搜索几天后,我使用料斗反汇编器反汇编了UIKitCore.framework
,发现setSelected:animated:
实际上是由touchesEnded:event:
方法调用的。实际上,实际上有一个内部setSelected:
方法,默认情况下会使用setSelected:animated:
来调用false
。而且,由于没有文档化的api只能让您突出显示一个单元格(不进行选择),并且在内部,setHighlighted:animated:
总是用false
来调用,所以拥有animated
的目的是什么该方法签名中的参数?
我没有找到很多例子。我所发现的涉及手动调用tableView.select:rowAtIndexPath:animated
的{{1}}可能是animated:true
或didSelectRow
。感觉很hacky,因为它两次调用willSelectRow
。
我确信我不是第一个实现自定义动画以突出显示和选择UITableViewCell的人。
到目前为止,这是我已经实现的,即使感觉很黑,它仍然可以工作。
setSelected:animated:
答案 0 :(得分:1)
我曾经在collectionview的不同单元中有一张图片。
let imageView: UIImageView = {
let iv = UIImageView()
iv.image = UIImage(named: "icon1")?.withRenderingMode(.alwaysTemplate)
iv.tintColor = UIColor.rgb(red: 91, green: 14, blue: 13)
return iv
}()
// Highlighted when pressed
override var isHighlighted: Bool {
didSet {
imageView.tintColor = isHighlighted ? UIColor.white : UIColor.rgb(red: 91, green: 14, blue: 13)
}
}
// When selected
override var isSelected: Bool {
didSet {
imageView.tintColor = isSelected ? UIColor.white : UIColor.rgb(red: 91, green: 14, blue: 13)
}
}
也许这给你一个主意。
答案 1 :(得分:0)
我得出的结论是,UITableView
上确实没有API可以像选择一样以编程方式突出显示{>使用UITableViewCell
在单元实例上调用setHighlighted:animated:
。在使用animated:true
查看UITableView
和UITableViewCell
的反汇编代码后,可以确认这一点。
通常,Hopper
和setHighlighted:animated:
都是由setSelected:animated:
触摸处理程序中的animated:false
调用的。有两个内部API函数UIView
和setHighlighted:
,它们在内部传递setAnimated:
,类似于以下内容:
animated: false
覆盖触摸处理程序不是一个合适的解决方案,因为func setSelected(_ selected: Bool) {
setSelected(selected, animated: false)
}
func setHighlighted(_ highlighted: Bool) {
setHighlighted(highlighted, animated: false)
}
func touches...(...) // the touch handlers {
// setSelected(selected)
// setHighlighted(highlighted)
}
实现中发生了许多其他事情。如果跳过它们,则可能会损坏单元的内部状态。但是,当您调用super
或任何其他触摸处理程序时,选择和突出显示方法将使用super.touchesBegan
进行调用。
此外,从Apple's documentation开始,如果您决定覆盖所有触摸处理程序,那么似乎应该覆盖所有触摸处理程序。
如果您在不调用super的情况下重写此方法(通常使用的模式),则即使您的实现不执行任何操作,也必须重写其他方法来处理触摸事件。
animated: false
您必须从这些处理程序返回func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
tableView.selectRow(at: indexPath, animated: true, scrollPosition: .none)
return indexPath
}
func tableView(_ tableView: UITableView, willDeselectRowAt indexPath: IndexPath) -> IndexPath? {
tableView.deselectRow(at: indexPath, animated: true)
return indexPath
}
,否则,将不会调用委托方法。但是,这意味着您现在将两次调用indexPath
。可以通过使用setSelected:animated:
来防止这种情况,如下所示。
guard
要设置高光动画,请使用以下命令:
override func setSelected(_ selected: Bool, animated: Bool) {
guard isSelected != selected else {
return
}
if animated {}
}
但是,这留下了最后一个漏洞,即func tableView(_ tableView: UITableView, shouldHighlightRowAt indexPath: IndexPath) -> Bool {
let cell = tableView.cellForRow(at: indexPath)
// there is no api on tableview to highlight the cell.
// so you must invoke highlight directly on the cell.
cell?.setHighlighted(true, animated: true)
return true
}
override func setHighlighted(_ highlighted: Bool, animated: Bool) {
guard isHighlighted != highlighted else {
return
}
if animated {}
}
时,您实际上并不知道是否对其进行动画处理。您可以在单元格中保留局部变量以保持其跟踪。