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の背景色が見えたりして、スムーズなスクロールに見えません。

画像の説明をここに入力

UICollectionViewcontentInsetを設定した場合、すべてのセルへ問題なくスクロール移動するにはどうしたらいいでしょうか?

上の例でいうセル1へのより良いスクロール方法がありましたら、教えていただけませんでしょうか?

よろしくお願いいたします。