본문 바로가기

아이폰/안드 개발자 시점

[iOS] CollectionView 선택한 아이템 UI 변경하기

반응형

해당 포스팅은 선택한 아이템의 UI를 변경해주는걸 중점으로 다뤘으며 UICollectionView에대한 기초적인 내용은 제 블로그내 다른 포스팅을 참고해주세요 

 

[iOS] CollectionView로 구현하는 페이징 & 리스트

안드로이드에선 페이징 기능 구현시 뷰페이저를 사용하고 리스트는 리싸이클러뷰를 사용합니다. iOS의 경우 페이징 과 리스트 모두 CollectionView로 구현이 가능합니다.  페이징 기능의 예로 5초

superwony.tistory.com

 

| 선택한 아이템 UI 예시 및 안드로이드와 비교

식물일기 메인 예시

위 사진 왼쪽 식물 리스트를 보시면 선택중인 식물은 다르게 표기하고 있습니다. 이처럼 목록중에서 선택한 아이템만 다르게 표기하는건 흔하게 쓰이는 UI 입니다. 

안드로이드에선 Recyclerview 아이템에 클릭 이벤트 발생시 선택한 아이템의 index를 저장하고 전체 리스트를 다시 그리는 메소드를 호출합니다. ( notifydatasetchange )

iOS도 비슷하게 구현해서 아이템 클릭시 리스트 전체 리스트를 다시 그리면(reloadData) 부담이 커서 선택한 셀 UI 변경시엔 사용하지 않는다고 하네요 (tableView 동일 ) 

| Cell.swift 

cell의 isSelected를 override하면 아이템을 클릭했을때 isSelected에 작성해놓은데로 변경됩니다. 그렇기 때문에 셀에 별도 버튼을 넣고 이벤트를 연결해주지 않아도 UI를 변경할 수 있습니다. 

class SelectYearCell: UICollectionViewCell {
    
    override var isSelected: Bool{
        didSet {
                if isSelected {
                    viewBg.isHidden = false
                } else {
                    viewBg.isHidden = true
                }
            }
    }

    @IBOutlet weak var viewBg: UIView!

}

| 아이템 선택시 인덱스 값 저장하기

아이템을 선택했을때 UI 변경도 중요하지만 최종적으로 선택한 값을 로컬 디비에 저장한다거나 서버로 보내는게 일반적입니다. 

Controller에서 didSelectItemAt을 이용해 선택한 인덱스 값을 저장하거나 아이템 변경도 가능합니다. 하지만 cell class에서 isSelected를 오버라이드 할 경우 별도 변경을 진행할 필요는 없습니다. ( 한군데서만 하는게 유지보수에 용이 ) 

class SelectYearController: UIViewController,UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout{
    
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        print("click index=\(indexPath.row)")
        let cell  = collectionView.cellForItem(at: indexPath) as! SelectYearCell
        selectStartYearPos = indexPath.row
        
    }
    
}

선택이 해제될 경우 호출되는 didDeselectItemAt 메소드가 존재하지만 꼭 필요한 경우가 아니라면 굳이 쓰지 않아도 선택한 아이템에대한 처리는 위 코드로 가능합니다. 

| 앱 구동시 default 아이템 select 시키기 

일반적으로 리스트에서 아이템을 선택할 수 있다면 제일 첫번째 값을 기본으로 선택된 상태를 보여줍니다. 그럴때 사용하면 됩니다.

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        
        let cell = startYearList.dequeueReusableCell(withReuseIdentifier: "SelectYearCell", for: indexPath) as! SelectYearCell
        
        if(indexPath.row == selectStartYearPos){
            collectionView.selectItem(at: indexPath, animated: false, scrollPosition: .init())
        }
        
        cell.isSelected = indexPath.row == selectStartYearPos
        
        return cell
    }

다른 예제에는 초기값(index = 0 ) cell.isSelect = true 를 해주는게 대부분인데 저의 경우 선택되지 않은 아이템에대한 처리를 위처럼 해줘야만 정상적으로 작동했습니다.

 

관련하여 궁금하신 내용은 댓글로 남겨주세요 ! 

 

 

반응형