section.visibleItemsInvalidationHandler = { [weak self] (visibleItems, offset, env) in
if let currentIndex = visibleItems.last?.indexPath.row {
self?.bannerIndex.accept(currentIndex)
}
visibleItemsInvalidationHandle에서 셀의 인덱스를 넘길 때 해결하지 못한 문제가 있다.
현재 하단 콜렉션뷰를 구성할 때 스크롤이 가능하다는 디자인을 위해 두번쨰 셀도 살짝 보이도록 구현해놨는데 이렇게 구현 시 visibleItems은 2개가 된다.
if let currentIndex = visibleItems.last?.indexPath.row
즉 해당 코드가 2번째 보여지는 셀부터 시작하게되어 최종적으로 마지막 셀이 스크롤될 때 인덱스가 1 부족한 상태가 되어 버린다.
guard let self = self else { return }
let width = self.storeCollectionView.bounds.width
let scrollOffset = offset.x
let modulo = scrollOffset.truncatingRemainder(dividingBy: width)
let tolerance = width / 3
if modulo < tolerance {
self.bannerIndex.accept(Int(scrollOffset/width))
}
let bannerIndex = Int(max(0, round(offset.x / env.container.contentSize.width)))
if env.container.contentSize.height == env.container.contentSize.width {
print(bannerIndex)
}
if let maxScaleItem = visibleItems.max(by: { $0.transform3D.m11 < $1.transform3D.m11 }) {
let maxScaleIndex = maxScaleItem.indexPath.row
self?.bannerIndex.accept(maxScaleIndex)
}
현재 보여지는 셀의 scale이 가장 클 때 index를 넘기기 위한 노력을 해봤지만, 잘 구현이 되지 않았다.
화면 한개에 셀 하나를 보여주고 스크롤이 가능하다는 디자인을 넣도록 해야할 거 같다.
[x] 마커 선택 시 하단 콜렉션뷰도 같이 이동되면서 마커의 카메라가 계속 변경되는 이슈
마커를 선택할 때마다 selectItem(at: IndexPath(row: index, section: 0), animated: true, scrollPosition: .centeredHorizontally
이벤트가 발생해서 컬렉션 뷰 스크롤 시 Observable에 값이 계속 방출되었다.
section.visibleItemsInvalidationHandler = { [weak self] (visibleItems, offset, env) in
visibleItems.forEach { item in
let intersectedRect = item.frame.intersection(CGRect(x: offset.x, y: offset.y, width: env.container.contentSize.width, height: item.frame.height))
let percentVisible = intersectedRect.width / item.frame.width
if percentVisible >= 1.0 {
if let currentIndex = visibleItems.last?.indexPath.row {
self?.visibleItemsRelay.accept(currentIndex)
}
}
visibleItemsInvalidationHandler
에서 스크롤 시 visibleItemsRelay
에 인덱스를 방출한다.// didScrollStoreCollectionView == visibleItemsRelay
input.didScrollStoreCollectionView
.distinctUntilChanged()
.withUnretained(self)
.bind(onNext: { owner, percentVisible in
guard let index = percentVisible else { return }
let store = owner.storeList[index]
output.setCameraPosition.accept((store.y, store.x))
output.selectedMarkerIndex.accept(index)
})
.disposed(by: disposeBag)
selectItem
애니메이션이 생길 때마다 카메라가 여러 마커를 들렸다 오는 것을 볼 수 있다.locationView.visibleItemsRelay.asObservable().debounce(.milliseconds(300), scheduler: MainScheduler.asyncInstance)
debounce
를 걸었다.debounce
**는 일정 시간동안 새로운 이벤트가 없을 때에만 이벤트를 전달하며, 중간에 들어오는 이벤트들을 무시한다.