如何为 UICollectionView 单元格选择设置动画
How to animate a UICollectionView cell selection
UICollectionView
的这些方法的 animated
参数是做什么的:
-
selectItem(at indexPath: IndexPath?, animated: Bool, scrollPosition: UICollectionViewScrollPosition)`
-
deselectItem(at indexPath: IndexPath, animated: Bool)
我知道我可以使用 UICollectionViewLayout
对象来动画更改。我也知道我可以使用 UICollectionViewDelegate
的 didSelect
和 didDeselect
方法来获取选定的单元格并应用动画。但是我找不到关于上述 animated
参数如何影响动画的任何信息。它会以任何方式影响布局动画吗?我的目标是创建一个 UICollectionView
子类,并允许消费者自定义在内部调用上述两个方法时是否应用动画。但是我不知道那些方法控制的是什么动画。
UICollectionView
的 selectItem(at:animated:scrollPosition:)
中的 animated
确定项目 to-be-selected 如果不在视图中或已经在所需位置,是否应滚动到动画时尚与否。
如果它在视图中,那么这个 animated
属性 并没有真正做任何事情,afaik。
deselectItem(at:animated:)
中的 animated
也一样。它什么都不做,就在那里。
我看到的唯一影响布局引擎的是,如果 collectionView
滚动并且您在 didSelectItemAt
中有动画,那么它会使这些动画无效。您将不得不延迟单元格中发生的动画(请参阅此答案中的最后一个示例)
如您所知,但对于其他人来说,如果您想为单元格选择事件设置动画,那么您必须在 collectionView(_:didSelectItemAt:)
委托中自己完成。
示例:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let cell = collectionView.cellForItem(at: indexPath)
//Briefly fade the cell on selection
UIView.animate(withDuration: 0.5,
animations: {
//Fade-out
cell?.alpha = 0.5
}) { (completed) in
UIView.animate(withDuration: 0.5,
animations: {
//Fade-out
cell?.alpha = 1
})
}
}
如果用户点击一个单元格,上面的内容很好,但如果你以编程方式调用 selectItem(at:animated:scrollPosition:)
,它不会触发上面的 collectionView(_:didSelectItemAt:)
委托,你需要显式调用它 运行你的选择动画。
示例(Add-on 到上一个):
func doSelect(for aCollectionView: UICollectionView,
at indexPath: IndexPath) {
aCollectionView.selectItem(at: indexPath,
animated: true,
scrollPosition: .centeredVertically)
//DispatchQueue after sometime because scroll animation renders
//the animation block in `collectionView(_:didSelectItemAt:)` ineffective
DispatchQueue.main.asyncAfter(deadline: .now() + 0.27) { [weak self] in
self?.collectionView(aCollectionView,
didSelectItemAt: indexPath)
}
}
我建议用动画覆盖 UICollectionViewCell
的 isHighlighted
属性。这样,如果用户点击一个单元格并停止思考下一步该做什么,动画状态将被保留。
override var isHighlighted: Bool {
didSet {
toggleIsHighlighted()
}
}
func toggleIsHighlighted() {
UIView.animate(withDuration: 0.1, delay: 0, options: [.curveEaseOut], animations: {
self.alpha = self.isHighlighted ? 0.9 : 1.0
self.transform = self.isHighlighted ?
CGAffineTransform.identity.scaledBy(x: 0.97, y: 0.97) :
CGAffineTransform.identity
})
}
UICollectionView
的这些方法的 animated
参数是做什么的:
-
selectItem(at indexPath: IndexPath?, animated: Bool, scrollPosition: UICollectionViewScrollPosition)`
-
deselectItem(at indexPath: IndexPath, animated: Bool)
我知道我可以使用 UICollectionViewLayout
对象来动画更改。我也知道我可以使用 UICollectionViewDelegate
的 didSelect
和 didDeselect
方法来获取选定的单元格并应用动画。但是我找不到关于上述 animated
参数如何影响动画的任何信息。它会以任何方式影响布局动画吗?我的目标是创建一个 UICollectionView
子类,并允许消费者自定义在内部调用上述两个方法时是否应用动画。但是我不知道那些方法控制的是什么动画。
UICollectionView
的 selectItem(at:animated:scrollPosition:)
中的 animated
确定项目 to-be-selected 如果不在视图中或已经在所需位置,是否应滚动到动画时尚与否。
如果它在视图中,那么这个 animated
属性 并没有真正做任何事情,afaik。
deselectItem(at:animated:)
中的 animated
也一样。它什么都不做,就在那里。
我看到的唯一影响布局引擎的是,如果 collectionView
滚动并且您在 didSelectItemAt
中有动画,那么它会使这些动画无效。您将不得不延迟单元格中发生的动画(请参阅此答案中的最后一个示例)
如您所知,但对于其他人来说,如果您想为单元格选择事件设置动画,那么您必须在 collectionView(_:didSelectItemAt:)
委托中自己完成。
示例:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let cell = collectionView.cellForItem(at: indexPath)
//Briefly fade the cell on selection
UIView.animate(withDuration: 0.5,
animations: {
//Fade-out
cell?.alpha = 0.5
}) { (completed) in
UIView.animate(withDuration: 0.5,
animations: {
//Fade-out
cell?.alpha = 1
})
}
}
如果用户点击一个单元格,上面的内容很好,但如果你以编程方式调用 selectItem(at:animated:scrollPosition:)
,它不会触发上面的 collectionView(_:didSelectItemAt:)
委托,你需要显式调用它 运行你的选择动画。
示例(Add-on 到上一个):
func doSelect(for aCollectionView: UICollectionView,
at indexPath: IndexPath) {
aCollectionView.selectItem(at: indexPath,
animated: true,
scrollPosition: .centeredVertically)
//DispatchQueue after sometime because scroll animation renders
//the animation block in `collectionView(_:didSelectItemAt:)` ineffective
DispatchQueue.main.asyncAfter(deadline: .now() + 0.27) { [weak self] in
self?.collectionView(aCollectionView,
didSelectItemAt: indexPath)
}
}
我建议用动画覆盖 UICollectionViewCell
的 isHighlighted
属性。这样,如果用户点击一个单元格并停止思考下一步该做什么,动画状态将被保留。
override var isHighlighted: Bool {
didSet {
toggleIsHighlighted()
}
}
func toggleIsHighlighted() {
UIView.animate(withDuration: 0.1, delay: 0, options: [.curveEaseOut], animations: {
self.alpha = self.isHighlighted ? 0.9 : 1.0
self.transform = self.isHighlighted ?
CGAffineTransform.identity.scaledBy(x: 0.97, y: 0.97) :
CGAffineTransform.identity
})
}