CollectionView로 정렬된 애니메이션 만들기

소개



콘텐츠가 타일 형태로 나열된 화면에서 정렬 순서 변경
타일이 움직이는 애니메이션을 구현할 필요가 있었지만,
여러가지 조사해도 섹션 헤더를 포함하여 애니메이션하는 방법을 찾지 못했습니다.
따라서 시행 착오하면서 자력으로 구현하기 시작...
아직도 미묘한 부분도 있습니다만, 우선 형태가 되었기 때문에 지견을 남기는 의미도 담아 기사로 했습니다.
마사카리 환영합니다!

이미지





화면 구성



정렬 순서를 전환하기 위한 SegmentedControl
타일을 표시하는 CollectionViewController

실현 방법



데이터를 잡는 방법


// セクション情報
struct Section {
    let title: String?
    let students: [Student]
}

// セクション内のタイル情報
struct Student {
    let id: Int
    let name: String
    let birthday: Date
    let height: Int
}

// 実データ
var sections: [Section]?

애니메이션을 만드는 방법



애니메이션을 실현하려면 performBatchUpdates 을 이용합니다.
이 메소드는, 블록내에 기술된 insert, delete, update의 애니메이션을 동시에 실행해 주는 메소드입니다.
위 메소드의 블록 내에서, 정렬 전의 IndexPath와 정렬 후의 IndexPath를 매칭시켜, moveItem(at: to:)로 이동시킵니다.
※ 이 방법에서는 섹션수의 가변이 매우 어렵기 때문에, 후술의 한가지 고안이 필요하게 됩니다.
let newSections = 並び替え後のデータ

collectionView.performBatchUpdates({
    並び替え前のIndexPathと並び替え後のIndexPathをマッチングさせる処理
    マッチしたアイテムの分だけ繰り返し {
        collectionView.moveItem(at: 並び替え前のIndexPath, to: 並び替え後のIndexPath)
    }
    self.sections = newSections // 1.
}, completion: { success in
    self.collectionView.reloadSections(IndexSet(integersIn: 0..<self.collectionView.numberOfSections) // 2.
})
  • performBatchUpdates 실행 후 CollectionView의 다시 그리기 처리가 수행되므로 데이터를 업데이트하지 않으면 섹션 수와 섹션의 항목 수를 처리하는 데 실패합니다.
  • 섹션이나 항목의 표시 내용에 대한 업데이트가있는 경우 performBatchUpdates에서 실행하면 애니메이션이 더 이상 실행되지 않으므로 완료 후 수행해야합니다.

    세션 수를 변경하려면



    애니메이션을 만드는 방법으로 가볍게 접했습니다만, 상기의 방법으로는 세션수의 가변이 어렵습니다.

    왜냐하면, performBatchUpdates의 특징으로서, 이동시키는 대상의 IndexPath와 삭제하는 대상의 IndexPath가 일치하는 경우에 에러가 된다고 하는 특징이 있기 때문입니다.
    이 특징에 의해, 세션을 줄이려고 하면 moveItem과 deleteSection의 IndexPath가 피해 버려 에러가 되어 버립니다.

    따라서 처음에는 세션 수를 변경할 수 있습니다.
    무슨 말인지 말하면, 세션수가 감소하는 경우는 빈 세션을 말미에 추가해 그 세션 헤더를 비표시(사이즈 0)로 하는 것으로 의사적으로 세션수가 줄어든 상태를 생성하는 방법을 취한다 합니다.
    let newSections = self.newSections
    
    // これを追加する
    UIView.performWithoutAnimation {
        collectionView.performBatchUpdates({
            if collectionView.numberOfSections < newSections.count {
                for count in collectionView.numberOfSections..<newSections.count {
                    collectionView.insertSections(IndexSet(integer: count))
                    sections?.append(Section(title: nil, students: []))
                }
            }
        }, completion: nil)
    }
    
    collectionView.performBatchUpdates({
        並び替え前のIndexPathと並び替え後のIndexPathをマッチングさせる処理
        マッチしたアイテムの分だけ繰り返し {
            collectionView.moveItem(at: 並び替え前のIndexPath, to: 並び替え後のIndexPath)
        }
        self.sections = newSections
    }, completion: { success in
        self.collectionView.reloadSections(IndexSet(integersIn: 0..<self.collectionView.numberOfSections)
    })
    

    이것으로 의사적으로 섹션수의 가변을 실현할 수 있었습니다.

    사이고에게



    의외와 요건으로서 나올 것 같고 정보가 전혀 없었기 때문에 어떻게든 만들어 보았습니다만,
    아직도 황삭한 방법이었던 마사카리를 바탕으로 브러쉬 업 해 가면 좋겠다고 생각합니다!

    참고



    【Swift】CollectionView를 재이해한다
    공식 참조

    코드



    검증 용으로 작성한 코드이므로 비교적 적절하지만 그래도 좋으면
    htps : // 기주 b. 코 m / 리 히텐 b / 페 r 후 rm 바 t 츄 p 다테세 mp ぇ
  • 좋은 웹페이지 즐겨찾기