본문 바로가기

SwiftUI/Project

3. SwiftUI 페이지 뷰와 인디케이터 애니메이션(1)

// 내용 추가중

 

 

어플리케이션에서 스크롤 뷰(scrollview)에 사진을 담은 후, 각각을 보기 편하게 하기 위해 페이지뷰를 이용한다.

이번에 만들 기능은 페이지 뷰(page view)에 인디케이터(indicator)를 넣고 애니메이션을 추가해 줬다.

 

단순한 애니메이션이 아니라, 페이지가 이동한 offset 만큼만 동적으로 변하게 하기 위해 UIViewRepresentable 프로토콜을 이용해 UIKit을 가져와 이용할 것이다.

 

2021.08.10 - [SwiftUI/기타] - SwiftUI에서 UIKit 이용하기: UIViewRepresentable

 

이번 글에서는 UIViewRepresentable을 이용하여 ScrollView에서 스크롤하며 스크롤 된 정도인 offset을 받아오는 기능적인 부분을 설명하고, 다음 글에서는 이를 실제 SwiftUI에서 불러와 보기 좋게 이런 저런 modifiers를 붙여볼 생각이다.

 

우선, PagingTabView.swift 로 이름 짓고 스크롤 뷰를 만들고 몇 가지 추가하자. 우리는 스크롤 뷰를 이용할 것이므로 UIScrollView를 적재 적소에 명시해준다.

// PagingTabView.swift

import SwiftUI

struct PagingTabView<Content: View>: UIViewRepresentable {
    
	init() {
	}
	
	func makeUIView(context: Context) -> UIScrollView {
	}
	
	func updateUIView(_ uiView: UIScrollView, context: Context) {
	}
	
}

기본적으로 살펴볼 문법

  • Type Constraints in Generic Type

몇 가지 추가해주자

struct PagingTabView<Content: View>: UIViewRepresentable {
	
	var content: Content
	@Binding var offset: CGFloat		
	
	init(offset: Binding<CGFloat>, @ViewBuilder content: @escaping () -> Content) {
		self.content = content()
		self._offset = offset
		
	}
	
	func makeUIView(context: Context) -> UIScrollView {
		
		let scrollView = UIScrollView()
		
        	// SwiftUI 뷰를 UIKit을 이용하기 위해
		let hostview = UIHostingController(rootView: content)
        
        	// 뷰 고정 
		hostview.view.translatesAutoresizingMaskIntoConstraints = false
		let constraints = [
			hostview.view.topAnchor.constraint(equalTo: scrollView.topAnchor),
			hostview.view.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor),	
			hostview.view.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),	
			hostview.view.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor ),			
			hostview.view.heightAnchor.constraint(equalTo: scrollView.heightAnchor)
		]
		
        	// UIView에 SwiftUI View 통합
		scrollView.addSubview(hostview.view)
		scrollView.addConstraints(constraints)
		
		// 페이징 설정
		scrollView.isPagingEnabled = true
		scrollView.showsVerticalScrollIndicator = false
		scrollView.showsHorizontalScrollIndicator = false
		
		return scrollView
	}

	
}

 

알아둘 개념

  • @ViewBuilder
  • @escaping

 

여기서 delegate와 coordinator 설정을 해주면 끝

import SwiftUI

struct PagingTabView<Content: View>: UIViewRepresentable {
	
	...
    
	func makeCoordinator() -> Coordinator {
		return PagingTabView.Coordinator(parent: self)
	}
	
	init(offset: Binding<CGFloat>, @ViewBuilder content: @escaping () -> Content) {
		...
	}
	
	func makeUIView(context: Context) -> UIScrollView {
		
		...
		
		scrollView.delegate = context.coordinator
		
		return scrollView
	}
	
	func updateUIView(_ uiView: UIScrollView, context: Context) {
		
	}
	
	// offset 받기 위해 delegate 설정
	class Coordinator: NSObject, UIScrollViewDelegate {
		var parent: PagingTabView
		
		init(parent: PagingTabView) {
			self.parent = parent
		}
		
		func scrollViewDidScroll(_ scrollView: UIScrollView) {
        		// 오프셋 받는 부분
			let offset = scrollView.contentOffset.x
			
			parent.offset = offset
		}
	}
	
}

 

 

 

참고 자료

https://www.youtube.com/watch?v=cY-Feaqkbng