contentInsetを設定するとscrollToItem(..)でスクロール移動できないセルが発生する現象を回避するには?
collectionViewで指定セルまでスクロールさせたいのですが、contentInsetを設定すると scrollToItem(at:at:animated:)メソッドではスクロール移動できないセルが発生して困っております。
問題を分かりやすくするために、以下のような横スクロールのコレクションビューを作成してみました。数字を表示するだけのセルを隙間なく並べたコレクションビューです。(下図にあるセルの境界線はUICollectionViewCellカスタムサブクラスのサブビュー(UIView)によるものです。)
「SCROLL」ボタンをタップするとUITextFieldに入力した数字と同じitemまで自動スクロールします。指定セルが中心に表示されるよう、左右に1セル幅分だけcontentInsetを設定しています。
let cellWidth: CGFloat = 50
collectionView?.contentInset = UIEdgeInsets(top: 0, left: cellWidth, bottom: 0, right: cellWidth)
セル3つ分の幅のコレクションビューなのですが、セル1を指定した場合のみ思うように動作してくれません。
【 問題点 】
- セル0の時にセル1を指定すると、スクロールしない
- セル2以上の時にセル1を指定すると、スクロールし、中央がセル0になる
上の例では、「SCROLL」ボタンをタップしたタイミングで、scrollToItem(at:at:animated:)を呼び出しています。
@objc private func handleScrollButtonTap(_ sender: UIButton) {
if let text = textField.text, let number = Int(text) {
selectedNumberLabel.text = text
// テキストフィールドで指定された番号のセルまでスクロール
let indexPath = IndexPath(item: number, section: 0)
collectionView.scrollToItem(at: indexPath, at: .centeredHorizontally, animated: true)
}
textField.resignFirstResponder()
textField.text = nil
}
対策として、セル1のみで発生するので、セル1の場合のみUIView.animate(..)を用い contentOffset.xをアニメーションさせて他のスクロールと同様に見せかける方法を試したのですが、
if number == 1 {
UIView.animate(withDuration: 0.2, animations: {
self.collectionView.contentOffset.x = 0
})
}
else {
let indexPath = IndexPath(item: number, section: 0)
collectionView.scrollToItem(at: indexPath, at: .centeredHorizontally, animated: true)
}
離れたセルからセル1にスクロール移動する場合に、間のセルが自動補完されないため、数字が消えたりcollectionViewの背景色が見えたりして、スムーズなスクロールに見えません。
UICollectionViewでcontentInsetを設定した場合、すべてのセルへ問題なくスクロール移動するにはどうしたらいいでしょうか?
上の例でいうセル1へのより良いスクロール方法がありましたら、教えていただけませんでしょうか?
よろしくお願いいたします。

