테이블뷰 인스타그램 검색 화면 애니메이션
func scrollViewWillEndDragging 를 이용해 구현하였다.
pointee를 이용해 내가 가리키고 있는 y축이 게시물의 절반을 넘어갈 때
화면이 밑으로 이동해 화면 맨 위에 cell의 top이 딱 걸리도록 하는
마치 인스타그램 검색 화면과 같이 딱딱 넘어가는 테이블 뷰를 만들고 싶은 게 목적!
기본적으로
imageTableView.decelerationRate = .fast
imageTableView.contentInsetAdjustmentBehavior = .never
TableView의 스크롤 속도를 높이고,
ScrollView의 Content 영역에 Safe Area Insets을 never로 주어 inset을 없애고 시작하였다.
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
// 내가 가리키고 있는 y축 : 빨리 스크롤을 하면 더 많이 가서 도착할 지점, 적게 스크롤을 하면 적게 가서 도착할 지점
let num = Int(targetContentOffset.pointee.y)
var targetOffsetY = CGFloat(num + (540 - num % 540))
if num % 540 >= 270 {
} else {
targetOffsetY = CGFloat(num - num % 540)
}
targetContentOffset.pointee.y = targetOffsetY
}
targetContentOffset을 이용하여 구현할 수 있다.
tableviewcell의 높이를 540으로 고정해두었기 때문에
내가 밑 방향으로 스크롤을 해서 놓았을 때 멈추는 지점이
270보다 크면
그대로 흘러가서 다음 cell의 위에 걸치고,
아니면
다시 내 cell의 위에 걸치게 targetOffsetY를 계산하여 적용하였다.
targetContentOffset.pointee.y는 내가 스크롤을 했을 때 멈출 y좌표를 뜻한다!
내가 가리키고 있는 y축 : 빨리 스크롤을 하면 더 많이 가서 도착할 지점, 적게 스크롤을 하면 적게 가서 도착할 지점
구현 완료한 모습
하지만 맨 첫 번째 셀부터 알 수 있듯이,
틱틱거리는 현상이 나타난다!
역방향의 애니메이션은 구현되어있지 않기 때문.
무슨 말이냐,
-> 내가 스크롤해서 내린 방향과 도달해야하는 방향이 다른 경우
-> 너무 작게 올리거나 작게 내린 경우
-> 다시 원래 게시물로 돌아와야하는 경우!
이를 방지하는 방법은 코드로 설명하겠다.
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
// 내가 가리키고 있는 y축 : 빨리 스크롤을 하면 더 많이 가서 도착할 지점, 적게 스크롤을 하면 적게 가서 도착할 지점
let num = Int(targetContentOffset.pointee.y)
var targetOffsetY = CGFloat(num + (540 - num % 540))
if num % 540 >= 270 {
} else {
targetOffsetY = CGFloat(num - num % 540)
}
if scrollView.contentOffset.y < targetContentOffset.pointee.y {
// 아래로 내려가는 경우
if targetOffsetY > scrollView.contentOffset.y {
// 방향이 같음
// 내가 가야할 마지막 목적지로 pointee를 설정해준다.
targetContentOffset.pointee.y = targetOffsetY
} else {
// 방향이 다름
// 스크롤이 끝나자마자의 y축을 지금 가리키는 y축으로 만들어버린다 -> 스크롤 끝나자마자 멈추는 것처럼 마치 띡하고 멈춰버림
targetContentOffset.pointee.y = scrollView.contentOffset.y
// 그리고 나서 내가 향할 방향으로 animation을 줘서 물흐르듯 다시 만들어준다.
scrollView.setContentOffset(.init(x: 0, y: targetOffsetY), animated: true)
}
} else {
// 올라가는 경우
if targetOffsetY > scrollView.contentOffset.y {
// 방향이 다름
targetContentOffset.pointee.y = scrollView.contentOffset.y
scrollView.setContentOffset(.init(x: 0, y: targetOffsetY), animated: true)
} else {
// 방향이 같음
targetContentOffset.pointee.y = targetOffsetY
}
}
}
1. 스크롤을 내릴 때
1) 조금 내려서 다시 돌아와야하는 경우 (역방향)
2) 많이 내려서 다음 게시물로 넘어가는 경우 (정방향)
2. 스크롤을 올릴 때
1) 조금 올려서 다시 돌아와야하는 경우 (역방향)
2) 많이 올려서 이전 게시물로 넘어가는 경우 (정방향)
역방향일 경우 스크롤을 멈추게하고, 반대방향까지 animation을 주어 물흐르듯 만들어주면 이런 버그가 해결된다....!
이 버그는 Apple OS적 에러라, UI를 세세하게 신경써야하는 앱이라면 이런 부분까지 생각하며 구현하면 좋다.
아직 이런 내용은 찾아도 많이 나오지 않아 글로 남기게 되었다.
부드럽게 구현 완료한 모습