UICollectionView의 deleteItems에서 콘텐츠 Offset을 좋은 느낌으로 조정
개시하다
죄송하지만 2018년 말, UICollectionView 이야기입니다.deleteItems 등을 통해 콘텐츠 크기를 바꾸는 경우 콘텐츠 오프셋을 조정하는 방법이 이어진다.
예제
deleteItems(at:)와reloadItems(at:) 등을 통해 UICollectionView의 Item 부분을 업데이트하고 콘텐츠 Size가 변할 때 원칙적으로 콘텐츠 Offset는 변하지 않는다.
다음 그림에서 보듯이 현재 보이는 디스플레이 영역의 아래 부분을 축소할 때는 특별히 신경 쓸 필요가 없지만 위쪽이 축소(축소된 길이에 따라 달라질 수 있음)되면 이전에 보았던 요소가 디스플레이 영역을 넘어 현재의 위치가 한순간에 사라진다.
아래 그림에서 보듯이, 디스플레이 영역 이상의 부분은 축소해도 현재 위치를 잃지 않도록 content Offset을 조정하고 싶습니다.
사용자 정의 UICollectionViewLayout
deleteItems(at:)를 실행한 후 scrollToItem() 등으로 콘텐츠 오프셋을 변경하는 방법도 있지만 삭제된 애니메이션이 완성되면 이동하기 때문에 조화롭지 못함을 느낄 수 있습니다.삭제된 애니메이션에서 content Offset을 동시에 변경하려면 UICollection ViewLayout을 사용자 정의해야 합니다.
Item 업데이트 시 호출하는 방법
Item이 업데이트되면 UICollectionViewLayout의 다음 메서드가 호출됩니다.
deleteItems(at:)와reloadItems(at:) 등을 통해 UICollectionView의 Item 부분을 업데이트하고 콘텐츠 Size가 변할 때 원칙적으로 콘텐츠 Offset는 변하지 않는다.
다음 그림에서 보듯이 현재 보이는 디스플레이 영역의 아래 부분을 축소할 때는 특별히 신경 쓸 필요가 없지만 위쪽이 축소(축소된 길이에 따라 달라질 수 있음)되면 이전에 보았던 요소가 디스플레이 영역을 넘어 현재의 위치가 한순간에 사라진다.
아래 그림에서 보듯이, 디스플레이 영역 이상의 부분은 축소해도 현재 위치를 잃지 않도록 content Offset을 조정하고 싶습니다.
사용자 정의 UICollectionViewLayout
deleteItems(at:)를 실행한 후 scrollToItem() 등으로 콘텐츠 오프셋을 변경하는 방법도 있지만 삭제된 애니메이션이 완성되면 이동하기 때문에 조화롭지 못함을 느낄 수 있습니다.삭제된 애니메이션에서 content Offset을 동시에 변경하려면 UICollection ViewLayout을 사용자 정의해야 합니다.
Item 업데이트 시 호출하는 방법
Item이 업데이트되면 UICollectionViewLayout의 다음 메서드가 호출됩니다.
prepare(forCollectionViewUpdates:)
CustomFlowLayout.swift
class CustomFlowLayout: UICollectionViewFlowLayout {
var minIndexPath: IndexPath?
var maxIndexPath: IndexPath?
override func prepare(forCollectionViewUpdates updateItems: [UICollectionViewUpdateItem]) {
print("prepare(forCollectionViewUpdates:)")
super.prepare(forCollectionViewUpdates: updateItems)
guard
let minIndexPath = updateItems.compactMap({ $0.indexPathBeforeUpdate ?? $0.indexPathAfterUpdate }).min(),
let maxIndexPath = updateItems.compactMap({ $0.indexPathBeforeUpdate ?? $0.indexPathAfterUpdate }).max()
else { return }
print(" min index path:", minIndexPath)
print(" max index path:", maxIndexPath)
self.minIndexPath = minIndexPath
self.maxIndexPath = maxIndexPath
}
...
}
prepare(forCollectionViewUpdates:)에서 업데이트된 객체의 Item 메시지가 전송되었습니다.여기서 업데이트 범위를 파악하기 위해 업데이트 대상의 최소 및 최대 크기를 미리 유지합니다.targetContentOffset(forProposedContentOffset:)
CustomFlowLayout.swift
override func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint) -> CGPoint {
print("targetContentOffset(forProposedContentOffset:)")
let targetContentOffset = super.targetContentOffset(forProposedContentOffset: proposedContentOffset)
guard let collectionView = collectionView,
let minIndexPath = minIndexPath,
let maxIndexPath = maxIndexPath,
let minAttributes = layoutAttributesForItem(at: minIndexPath),
let maxAttributes = layoutAttributesForItem(at: maxIndexPath)
else { return targetContentOffset }
let viewTop = collectionView.contentOffset.y
let viewBottom = viewTop + collectionView.frame.size.height
print(" view range: \(viewTop) - \(viewBottom)")
let updateTop = minAttributes.frame.origin.y
let updateBottom = maxAttributes.frame.origin.y
print(" update range: \(updateTop) - \(updateBottom)")
let currentHeight = collectionView.contentSize.height
let newHeight = collectionViewContentSize.height
print(" current height:", currentHeight)
print(" new height:", newHeight)
if currentHeight > newHeight,
viewBottom > updateBottom {
let diff = currentHeight - newHeight
return CGPoint(x: targetContentOffset.x,
y: max(collectionView.contentOffset.y - diff, 0))
}
return targetContentOffset
}
이런 인상으로어수선하지만 영역 이상의 부분이 축소된 것으로 판단됐다.를 참고하십시오.진실로 판정된 상태에서 수축된 부분만 있다.y로 이동한 CGPoint를 반환합니다.
참고로 업데이트 전 (현재) 콘텐츠 크기는collectionView입니다.콘텐츠 Size에서 업데이트된 콘텐츠 Size는collectionViewContent Size를 통해 각각 얻을 수 있습니다.
finalizeCollectionViewUpdates()
CustomFlowLayout.swift
override func finalizeCollectionViewUpdates() {
print("finalizeCollectionViewUpdates()")
super.finalizeCollectionViewUpdates()
minIndexPath = nil
maxIndexPath = nil
}
당분간 최종 처리를 잊지 마라.끝맺다
이번에 만든 프로젝트는 아래 창고에 있어요.
https://github.com/imamurh/CollectionViewSample
Reference
이 문제에 관하여(UICollectionView의 deleteItems에서 콘텐츠 Offset을 좋은 느낌으로 조정), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/imamurh/items/5f83bcc20749e3356ea8
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
Reference
이 문제에 관하여(UICollectionView의 deleteItems에서 콘텐츠 Offset을 좋은 느낌으로 조정), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/imamurh/items/5f83bcc20749e3356ea8텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)