使用 UIPinchGestureRecognizer 延迟缩放动画 UICollectionView
Delay in zoom animation UICollectionView with UIPinchGestureRecognizer
请告诉我 "zoom in/out" UICollectionView
和更改 UICollectionViewCell
大小的最佳方法。我现在正在使用 UIPinchGestureRecognizer
:当 UICollectionView
是 "zoom in" 和 "zoom out" 时,会出现严重的延迟和冻结。
我如何在执行 PinchGestureRecognizer 时去除条纹?
这里是UICollectionViewController中UIPinchGestureRecognizer的实现代码:
class BlocksCollectionViewController: UICollectionViewController, UIGestureRecognizerDelegate {
private var senderStartSize = CGFloat()
private var senderNormalPosition = CGSize()
override func viewDidLoad() {
super.viewDidLoad()
let pinchRecognizer = UIPinchGestureRecognizer(target: self, action: #selector(handlePinch(_:)))
pinchRecognizer.delegate = self
collectionView?.addGestureRecognizer(pinchRecognizer)
}
@objc func handlePinch(_ sender: UIPinchGestureRecognizer) {
guard let collection = collectionView else { return }
guard let layout = collection.collectionViewLayout as? CustomCollectionViewLayout else { return }
switch sender.state {
case .began:
senderStartSize = layout.cellSize
case .changed:
layout.cellSize = senderStartSize * sender.scale
layout.invalidateLayout()
default:
break
}
}
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
}
下面的代码是сustom CollectionViewLayout:
class CustomCollectionViewLayout: UICollectionViewLayout {
private var cellAttributes: [IndexPath: UICollectionViewLayoutAttributes] = [:]
var cellSize: CGFloat = 7
private var contentSize = CGSize.zero
override var collectionViewContentSize: CGSize {
return self.contentSize
}
override func prepare() {
guard let collection = collectionView else { return }
for section in 0...collection.numberOfSections - 2 {
for item in 0...collection.numberOfItems(inSection: section) - 2 {
let cellIndex = IndexPath(item: item, section: section)
let xPos = CGFloat(item) * cellSize
let yPos = CGFloat(section) * cellSize
let attributes = UICollectionViewLayoutAttributes(forCellWith: cellIndex)
attributes.frame = CGRect(x: xPos, y: yPos, width: cellSize, height: cellSize)
cellAttributes[cellIndex] = attributes
}
}
let contentWidth = CGFloat(collection.numberOfItems(inSection: 0)) * cellSize
let contentHeight = CGFloat(collection.numberOfSections) * cellSize
contentSize = CGSize(width: contentWidth, height: contentHeight)
let centerOffsetX = (collection.contentSize.width - collection.frame.size.width) / 2
let centerOffsetY = (collection.contentSize.height - collection.frame.size.height) / 2
let centerPoint = CGPoint(x: centerOffsetX, y: centerOffsetY)
collection.setContentOffset(centerPoint, animated: false)
}
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
var attributesInRect = [UICollectionViewLayoutAttributes]()
for cellAttributes in cellAttributes.values {
if rect.intersects(cellAttributes.frame) {
attributesInRect.append(cellAttributes)
}
}
return attributesInRect
}
override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
return cellAttributes[indexPath]
}
}
result of this code (GIF)
抱歉这么说,但我的猜测是问题不在于您的代码,而在于它本身的工作方式。因为我看到你有大量的细胞,这使得它很难处理,这就是它开始滞后的原因。
你试过用真机吗?将最新款 iPhone 与旧款进行比较?我相信您会看到渲染速度的差异。
但无论如何,calculations/expressions 越多,它就会越慢。此外,循环很昂贵。
顺便说一句,作为一种解决方案(如果应用程序的业务方面接受它),您可以不缩放 in/out,而是使用 2 个缩放按钮 in/out。我认为它不会导致延迟,但它肯定没有捏的那么酷。
在这种情况下,我建议您使用 Xcode Time Profiler 来调试性能。您会找到导致延迟的部分并在稍后对其进行优化。祝你好运:)
由于我的collection里面有很多UICollectionViewCells,最好的办法是这样:
1) 把UICollectionView放在一个containerView(简单的UIView)上,把这个containerView放在UIScrollView上。
我限制缩放:
scrollView.minimumZoomScale = 1
scrollView.maximumZoomScale = 6
2) 并使用了 UIScrollViewDelegate 的功能:
func scrollViewDidZoom(_ scrollView: UIScrollView) {
// Code for processing zoom - scrollView.zoomScale,
// contentOffset, contentSize etc....
}
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return containerView
}
请告诉我 "zoom in/out" UICollectionView
和更改 UICollectionViewCell
大小的最佳方法。我现在正在使用 UIPinchGestureRecognizer
:当 UICollectionView
是 "zoom in" 和 "zoom out" 时,会出现严重的延迟和冻结。
我如何在执行 PinchGestureRecognizer 时去除条纹?
这里是UICollectionViewController中UIPinchGestureRecognizer的实现代码:
class BlocksCollectionViewController: UICollectionViewController, UIGestureRecognizerDelegate {
private var senderStartSize = CGFloat()
private var senderNormalPosition = CGSize()
override func viewDidLoad() {
super.viewDidLoad()
let pinchRecognizer = UIPinchGestureRecognizer(target: self, action: #selector(handlePinch(_:)))
pinchRecognizer.delegate = self
collectionView?.addGestureRecognizer(pinchRecognizer)
}
@objc func handlePinch(_ sender: UIPinchGestureRecognizer) {
guard let collection = collectionView else { return }
guard let layout = collection.collectionViewLayout as? CustomCollectionViewLayout else { return }
switch sender.state {
case .began:
senderStartSize = layout.cellSize
case .changed:
layout.cellSize = senderStartSize * sender.scale
layout.invalidateLayout()
default:
break
}
}
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
}
下面的代码是сustom CollectionViewLayout:
class CustomCollectionViewLayout: UICollectionViewLayout {
private var cellAttributes: [IndexPath: UICollectionViewLayoutAttributes] = [:]
var cellSize: CGFloat = 7
private var contentSize = CGSize.zero
override var collectionViewContentSize: CGSize {
return self.contentSize
}
override func prepare() {
guard let collection = collectionView else { return }
for section in 0...collection.numberOfSections - 2 {
for item in 0...collection.numberOfItems(inSection: section) - 2 {
let cellIndex = IndexPath(item: item, section: section)
let xPos = CGFloat(item) * cellSize
let yPos = CGFloat(section) * cellSize
let attributes = UICollectionViewLayoutAttributes(forCellWith: cellIndex)
attributes.frame = CGRect(x: xPos, y: yPos, width: cellSize, height: cellSize)
cellAttributes[cellIndex] = attributes
}
}
let contentWidth = CGFloat(collection.numberOfItems(inSection: 0)) * cellSize
let contentHeight = CGFloat(collection.numberOfSections) * cellSize
contentSize = CGSize(width: contentWidth, height: contentHeight)
let centerOffsetX = (collection.contentSize.width - collection.frame.size.width) / 2
let centerOffsetY = (collection.contentSize.height - collection.frame.size.height) / 2
let centerPoint = CGPoint(x: centerOffsetX, y: centerOffsetY)
collection.setContentOffset(centerPoint, animated: false)
}
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
var attributesInRect = [UICollectionViewLayoutAttributes]()
for cellAttributes in cellAttributes.values {
if rect.intersects(cellAttributes.frame) {
attributesInRect.append(cellAttributes)
}
}
return attributesInRect
}
override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
return cellAttributes[indexPath]
}
}
result of this code (GIF)
抱歉这么说,但我的猜测是问题不在于您的代码,而在于它本身的工作方式。因为我看到你有大量的细胞,这使得它很难处理,这就是它开始滞后的原因。
你试过用真机吗?将最新款 iPhone 与旧款进行比较?我相信您会看到渲染速度的差异。
但无论如何,calculations/expressions 越多,它就会越慢。此外,循环很昂贵。
顺便说一句,作为一种解决方案(如果应用程序的业务方面接受它),您可以不缩放 in/out,而是使用 2 个缩放按钮 in/out。我认为它不会导致延迟,但它肯定没有捏的那么酷。
在这种情况下,我建议您使用 Xcode Time Profiler 来调试性能。您会找到导致延迟的部分并在稍后对其进行优化。祝你好运:)
由于我的collection里面有很多UICollectionViewCells,最好的办法是这样:
1) 把UICollectionView放在一个containerView(简单的UIView)上,把这个containerView放在UIScrollView上。
我限制缩放:
scrollView.minimumZoomScale = 1
scrollView.maximumZoomScale = 6
2) 并使用了 UIScrollViewDelegate 的功能:
func scrollViewDidZoom(_ scrollView: UIScrollView) {
// Code for processing zoom - scrollView.zoomScale,
// contentOffset, contentSize etc....
}
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return containerView
}