Today’s Goal

  1. Review LBTA Youtube ep12
  2. Learn LBTA Youtube ep13
  1. Review LBTA ep 12

Swipe between sections horizontally

앱 전체 화면 flow를 가로로 swipe하는 구성을 만들기 위해 기존 collectionView 함수들을 지우고 새롭게 작성한다.

총 4개의 navigation bar icon이 있기 때문에 numberOfItemInSection에는 4를 return해준다.

let cell = collectionView.dequeuReusableCell(withReuseIdentifier: cellId, for: indexPath)

기존에는 VideoCell에서 cell을 만들어 collectionView를 구성했는데 이를 새롭게 바꿔준다.

총 4개의 cell을 만들었고 각각은 하나의 nav bar item을 담당하기 때문에

collectionView?.register(UICollectionViewCell.self, forCellWithReuseIdentifier: cellId)

collectionView에 사용할 Cell class를 default값인 UICollectionViewCell.self로 다시 새롭게 register해준다.

화면 스크롤을 Horizontal로 변경하기

  1. AppDelegate.swift
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal

flowLayout을 참조하여 변경

  1. HomeController.swift
if let flowLayout = collectionView?.collectionViewLayout as? UICollectionViewFlowLayout {
    flowLayout.scrollDirection = .horizontal
    flowLayout.minimumLineSpacing = 0
}

해당 collectionView의 collectionViewLayout을 FlowLayout으로 다운캐스팅해 변경하는 법

flowLayout의 minimumLineSpacing으로 cell간 간격을 조절한다.

스크롤을 한 페이지씩만 넘겨지도록 변경

collectionView?.isPagingEnabled = true

화면을 Swipe시 menu bar의 horizontal bar도 움직이게 만들자

  1. When you swipe pages
 override func scrollViewDidScroll(_ scrollView: UIScrollView) {
        menuBar.horizontalBarLeftAnchorConstraint?.constant = scrollView.contentOffset.x / 4
    }

스크롤이 끝날 때 마다 menuBar의 constraint를 변경해준다.

이제 무조건 스크롤이 움직이면 menuBar의 constraint도 바뀌게 된다.

  1. When you clicked menu bar icons
func scrollToMenuIndex(menuIndex: Int) {
        let indexPath = IndexPath(item: menuIndex, section: 0)
        collectionView?.scrollToItem(at: indexPath, at: .centeredHorizontally, animated: true)
    }

클릭하면 scroll을 이동시키게 하는 함수를 만들어서 호출한다.

scrollToItem()이라는 함수 이용

이 함수를 MenuBar에서 사용하기 위해서는 menuBar에도 homeController가 필요하다.

lazy var menuBar: MenuBar = {
    let mb = MenuBar()
    mb.homeController = self
    return mb
}()

HomeController에서 menuBar 선언 시 homeController를 self로 연결해주고 lazy var로 바꿔준다.

    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        // Horizontal Bar 이동하는 코드
        homeController?.scrollToMenuIndex(menuIndex: indexPath.item)
    }

MenuBar의 didSelectItem함수에서 scrollToMenuIndex를 호출.

  1. Change the highlighted icon when you swiped
override func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
        
        let index = Int(targetContentOffset.pointee.x / view.frame.width)
        let indexPath = IndexPath(item: index, section: 0)
        menuBar.collectionView.selectItem(at: indexPath, animated: true, scrollPosition: .centeredHorizontally)
    }

scrollviewtarget으로 호출, scroll이 끝날 때마다 target의 contentOffset을 가져오는 함수

targetContentOffset.pointee.x를 호출하면 스크롤이 끝날 때마다 375, 즉 view.frame.width 단위로 커지는 것을 확인할 수 있다.

이를 토대로 indexPath를 만들어서 menuBar.collectionView.selectItem을 호출한다.

그래서 swipe를 하면 스크롤이 끝난 후에 계산된 index의 menu bar icon을 클릭하게 되므로 highlighted icon이 바뀌게 된다.


  1. Learn LBTA ep13

Render Vertical Video Cells in Horizontal Layout

    override func viewDidLoad() {
        super.viewDidLoad()

        navigationController?.navigationBar.isTranslucent = false
        
        let titleLabel = UILabel(frame: CGRect(x: 0, y: 0, width: view.frame.width - 32, height: view.frame.height))
        titleLabel.text = "  Home"
        titleLabel.textColor = UIColor.white
        titleLabel.font = UIFont.systemFont(ofSize: 20)
        navigationItem.titleView = titleLabel
        
        setupCollectionView()
        setupMenuBar()
        setupNavBarButtons()
    }

현재 HomeController에는 numberOfItem이 4인 collectionView 하나가 horizontal인 상태로 존재 (4개의 navi bar아이템)

UICollectionView새롭게 넣을 Cell이 필요하다

FeedCellcocoa touch class로 새롭게 만든다. (subclass of BaseCell)

collectionView?.register(FeedCell.self, forCellWithReuseIdentifier: cellId)

따라서 기존에 default 값으로 등록해 놓았던 UICollectionViewCell class를 FeedCell로 바꾼다.

이제까지 Cell이름을 가지는 class는 BaseCell만 상속했다. BaseCell은 UICollectionViewCell을 상속하고있다.

하지만 FeedCell은 각 cell안에 또 collectionView를 넣을 것이기 때문에

class FeedCell: BaseCell, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout

다음과 같이 CollectionVIew의 요소들을 모두 상속해준다.

lazy var collectionView: UICollectionView = {
        let layout = UICollectionViewFlowLayout()
        let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
        cv.delegate = self
        cv.dataSource = self
        cv.backgroundColor = .white
        return cv
    }()

subview로 추가할 collectionView 선언에서 delegate와 dataSource를 self(FeedCell)로 지정해준다.

The object that acts as the delegate(provides the data) of the collection view.

이 collection VIew의 확장자(delegate), 데이터전달자(dataSource)를 모두 FeedCell로 지정한다는 소리

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return videos?.count ?? 0
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cellId", for: indexPath) as! VideoCell
        cell.video = videos?[indexPath.item]
        
        return cell
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        let height = (frame.width - 16 - 16) * 9 / 16
        return CGSize(width: frame.width, height: height + 16 + 80)
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
        return 0
    }

이전 VideoCell을 처음에 fetch 했을 때 사용했었던 collectionView 함수들을 다시 가져온다.

Change Navigation Bar Titles

ep 12에서 공부했던 것 같이 swipe section에서 특징은 homeController의 scroll 후의 행동과 MenuBar에서 didSelectItem 후 행동이 같은 결과를 가진다는 것

private func setTitleForIndex(index: Int) {
        if let titleLabel = navigationItem.titleView as? UILabel {
            titleLabel.text = "  \(titles[index])"
        }
    }

if let을 사용하여 title을 바꿔준다. 두번 쓰이기 때문에 추상화

override func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
        
        let index = Int(targetContentOffset.pointee.x / view.frame.width)
        let indexPath = IndexPath(item: index, section: 0)
        menuBar.collectionView.selectItem(at: indexPath, animated: true, scrollPosition: .centeredHorizontally)
        
        setTitleForIndex(index: index)
    }

먼저 scroll이 끝나면 실행되는 scrollViewWillEndDragging(a.k.a scrolltarget)함수에 넣어주고

func scrollToMenuIndex(menuIndex: Int) {
        let indexPath = IndexPath(item: menuIndex, section: 0)
        collectionView?.scrollToItem(at: indexPath, at: .centeredHorizontally, animated: true)
        
        setTitleForIndex(index: menuIndex)
    }

이전 highlighted icon을 처리할 때 사용했던 scrollToMenuIndex함수에 seTitleForIndex함수를 넣어준다. 같은 Index 사용

태그:

카테고리:

업데이트:

댓글남기기