[iOS | Swift] 화면 회전 시 CollectionViewLayout 형태 유지하는 방법

Minji Kim·2021년 12월 9일
0

iOS | Swift

목록 보기
2/13
post-thumbnail

CollectionView를 포함하여 개발하는 경우 화면 회전에 따라 Layout을 변경할 필요가 있다. 특히, iPad에서는 더욱 필요할 것이다.

데이터베이스나 API를 통해 데이터를 읽어와 CollectionView에 뿌려주는 경우 화면이 회전될 때마다 셀이 이상하게 보일 때가 있다.

따라서, CollectionView를 사용하는데 iPad에서도 사용 가능한 앱을 개발 중이라면 이 글을 읽어보길 바란다.

1. viewWillTransition 메서드 이용하기

화면이 회전될 때 호출되는 viewWillTransition 메서드를 이용할 것이다.
이 메서드가 호출될 때 CollectionViewFlowLayout 셀 크기를 resizing 해주면 된다.

필자는 따로 ResizeCells라는 함수를 만들어 호출했다.

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
        super.viewWillTransition(to: size, with: coordinator)
        ResizeCells(self.collectionview)
    }

2. CollectionViewFlowLayout Resizing

파라미터로 받아온 collectionView의 layout을 가져온다. 그리고 resizing 한 크기를 layout의 itemSize로 초기화한 후 layout.invalidateLayout() 해준다.

(invalidateLayout는 UICollectionView의 현재 레이아웃을 무효화하고 신규 레이아웃을 업데이트하는 것이다.)

func ResizeCells(_ collectionView: UICollectionView?) {
    if let layout = collectionView?.collectionViewLayout as? UICollectionViewFlowLayout {
        guard let _ = collectionView?.collectionViewLayout as? UICollectionViewFlowLayout else {
            layout.itemSize = CGSize.zero
            return
        }
        
        let width = ((collectionView?.bounds.width)! / 3) - 0.8
        let itemSize = CGSize(width: width, height: width)
        layout.itemSize = itemSize
        layout.invalidateLayout()
    }
}

전체 코드

// HomeViewController.swift
class HomeViewController: UIViewController {    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    // 화면 회전될 때
    override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
        super.viewWillTransition(to: size, with: coordinator)
        ResizeCells(self.collectionview)
    }
}

// MARK: - UICollectionView Configure
extension HomeViewController: UICollectionViewDataSource {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 0
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "HomeCollectionViewCell", for: indexPath) as? HomeCollectionViewCell else {
            return UICollectionViewCell()
        }
        return cell
    }
}

extension HomeViewController: UICollectionViewDelegate {
    
}

extension HomeViewController: UICollectionViewDelegateFlowLayout {
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        let width = (collectionView.bounds.width / 3) - 0.8
        return CGSize(width: width, height: width)
    }
}
// UIConfigure.swift
func ResizeCells(_ collectionView: UICollectionView?) {
    if let layout = collectionView?.collectionViewLayout as? UICollectionViewFlowLayout {
        guard let _ = collectionView?.collectionViewLayout as? UICollectionViewFlowLayout else {
            layout.itemSize = CGSize.zero
            return
        }
        
        let width = ((collectionView?.bounds.width)! / 3) - 0.8
        let itemSize = CGSize(width: width, height: width)
        layout.itemSize = itemSize
        layout.invalidateLayout()
    }
}

필자는 여러 viewController에서 CollectionView를 구성하였기 때문에 ResizeCells 메서드의 내용이 겹쳤고, 따로 함수로 구현하여 viewWillTransition이 호출될 때 ResizeCells 메서드를 호출했다.

profile
iOS Developer

0개의 댓글