36307


`collectionView`で指定セルまでスクロールさせたいのですが、`contentInset`を設定すると
`scrollToItem(at:at:animated:)`メソッドではスクロール移動できないセルが発生して困っております。

問題を分かりやすくするために、以下のような横スクロールのコレクションビューを作成してみました。数字を表示するだけのセルを隙間なく並べたコレクションビューです。（下図にあるセルの境界線は`UICollectionViewCell`カスタムサブクラスのサブビュー(`UIView`)によるものです。）

「SCROLL」ボタンをタップすると`UITextField`に入力した数字と同じ`item`まで自動スクロールします。指定セルが中心に表示されるよう、左右に１セル幅分だけ`contentInset`を設定しています。

[code]

    let cellWidth: CGFloat = 50
    collectionView?.contentInset = UIEdgeInsets(top: 0, left: cellWidth, bottom: 0, right: cellWidth)
    
[/code]

セル３つ分の幅のコレクションビューなのですが、セル１を指定した場合のみ思うように動作してくれません。

[![画像の説明をここに入力](https://i.stack.imgur.com/f9chK.gif)](https://i.stack.imgur.com/f9chK.gif)

【 問題点 】

  * セル０の時にセル１を指定すると、スクロールしない
  * セル２以上の時にセル1を指定すると、スクロールし、中央がセル０になる

上の例では、「SCROLL」ボタンをタップしたタイミングで、`scrollToItem(at:at:animated:)`を呼び出しています。

[code]

    @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
    }
    
[/code]

対策として、セル１のみで発生するので、セル１の場合のみ`UIView.animate(..)`を用い
`contentOffset.x`をアニメーションさせて他のスクロールと同様に見せかける方法を試したのですが、

[code]

      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)
      }
    
[/code]

離れたセルからセル１にスクロール移動する場合に、間のセルが自動補完されないため、数字が消えたり`collectionView`の背景色が見えたりして、スムーズなスクロールに見えません。

[![画像の説明をここに入力](https://i.stack.imgur.com/nVnHM.gif)](https://i.stack.imgur.com/nVnHM.gif)

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

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

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


CC BY-SA 3.0
2017-07-12T23:57:42.927
36302
2017-07-13T03:24:36.870
9833
question
swift ios uicollectionview uiscrollview
contentInsetを設定するとscrollToItem(..)でスクロール移動できないセルが発生する現象を回避するには？


試してみたところ、同様の現象を確認できました。

また、contentInsetのleftを１セル分よりも多く取ると2以降のインデックスでも同様に発生し、  
leftとrightを異なる値にするとすべてのインデックスで中央に揃わなくなる、  
などいろいろ起こるようです。

水平スクロールモードのUICollectionViewのバグだと思われますが、  
とりあえず回避するなら、

[code]

    UIView.animate(withDuration: 0.2, animations: {
      self.collectionView.contentOffset.x = 0
    })
    
[/code]

ではなく、
[setContentOffset(_:,animated:)](https://developer.apple.com/documentation/uikit/uiscrollview/1619400-setcontentoffset?language=swift)
を使うとよいと思います。


CC BY-SA 3.0
2017-07-13T03:13:23.983
36307
2017-07-13T03:24:36.870
2017-07-13T03:24:36.870
23829
23829
36302
answer