-
[iOS, Swift] (TagCalendar 컴포넌트 3) 뷰 위치 이동 시 특정 위치(그리드)에만 위치하게 하기iOS/UI 컴포넌트 2023. 6. 5. 18:30반응형
이전 포스팅에서는 뷰 충돌을 감지하여 충돌했을 때 원래의 위치로 돌아가게끔 하는 기능을 구현했었습니다.
[iOS, Swift] (TagCalendar 컴포넌트 2) 뷰의 충돌 감지하기
이전 포스팅에서 드래그하는 뷰를 만들었습니다. https://swift-apprentice.tistory.com/entry/iOS-Swift-TagCalendar-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8-1-%EC%9D%B4%EB%8F%99%ED%95%98%EB%8A%94-%EB%B7%B0-%EB%A7%8C%EB%93%A4%EA%B8%B0 [iOS, Swift
hhproject.me
이번 글에서는 뷰의 이동을 드래그해서 멈추는 곳에 위치하는 것이 아니라 드래그해서 멈추는 곳에서 가까운 특정 위치에 자리하게끔 하는 기능을 구현하겠습니다. 이렇게 하는 이유는 뷰들끼리의 위치를 미리 정함으로써 화면이 어지러운 것을 방지하고 사용자가 더 나은 앱 경험을 얻고자하기 위함입니다.
결과화면
특정한 위치에 뷰를 위치하도록 하면 위와 같은 결과화면을 만들 수 있습니다.
구현할 기능
- 뷰가 위치할 공간을 설정합니다. ( [CGPoint] 배열에 뷰가 이동할 수 있는 위치들을 저장합니다 )
- 뷰의 이동이 끝났을 때, 뷰 프레임의 위치와 가장 가까운 위치를 찾습니다.
- 가장 가까운 위치로 뷰의 프레임을 이동합니다.
Chap1. 뷰가 위치할 공간을 설정합니다
private var snapPoints: [CGPoint] = [] private var horizontalSnapCount = 3 private var verticalSnapCount = 3 private func setupSnapPoints() { snapPoints.removeAll() let gridSize: CGFloat = 10.0 for i in 0..<horizontalSnapCount { for j in 0..<verticalSnapCount { let x = CGFloat(i) * (frame.width + gridSize) + gridSize let y = CGFloat(j) * (frame.height + gridSize) + gridSize snapPoints.append(CGPoint(x: x, y: y)) } } }
뷰가 위치할 공간을 담을 배열은 snapPoints 입니다. 가로와 세로의 수에 따라서 뷰를 담을 것이기 때문에 가로와 세로의 개수를 셀 수 있는 변수를 만들었습니다.
그리고 for문을 돌면서 뷰가 위치할 3*3의 공간이 만들어졌습니다.
Chap2. 뷰의 이동이 끝났을 때 가장 가까운 위치를 찾고 위치를 이동시킵니다.
private func finishDrag() { state = .ended if let closestSnapPoint = snapPoints.min(by: { distance($0, frame.origin) < distance($1, frame.origin) }) { UIView.animate(withDuration: 0.2) { self.frame.origin = closestSnapPoint } } DispatchQueue.main.async { [self] in if let superview = superview { for subview in superview.subviews { if let tagView = subview as? MovingView, tagView != self, isOverlapping(with: tagView) { UIView.animate(withDuration: 0.2) { self.frame.origin = self.originalPosition } } } } } } private func distance(_ point1: CGPoint, _ point2: CGPoint) -> CGFloat { return sqrt(pow(point1.x - point2.x, 2) + pow(point1.y - point2.y, 2)) }
distance 함수는 두 점의 위치가 얼마나 떨어져 있는지 거리를 구하는 함수입니다.
snapPoints의 값들과 view의 위치를 비교하여 가장 가까운 거리를 찾게 됩니다.
그 후에 기존에 작업했던 뷰가 들어갈 공간에 뷰 프레임을 위치시키게 됩니다.
전체 소스
반응형'iOS > UI 컴포넌트' 카테고리의 다른 글
[iOS, Swift] (TagCalendar 컴포넌트 2) 뷰의 충돌 감지하기 (0) 2023.06.02 [iOS, Swift] (TagCalendar 컴포넌트 1) 이동하는 뷰 만들기 (0) 2023.06.01