2021年7月5日月曜日

画面幅より短い場合はCenterさせるUIScrollViewを作成する

次のようなViewを条件を満たすViewを作りたくなったので実装してみました。
  • 画面幅より短い場合は、Center表示させる
  • 画面幅より長い場合は、左寄せで表示し横スクロール可能である

完成イメージは次のような感じです。

Viewの構成

Viewの構成は、UIScrollViewの中にコンテンツ用のUIViewを入れるのみです。
  1. private let scrollView = UIScrollView()
  2. private let contentView = UIView()
  3.  
  4.  
  5. private func setupViews() {
  6. scrollView.addSubview(contentView)
  7. addSubview(scrollView)
  8. }

実際に表示させたいViewは、次のようにfunc setup(_)メソッドを使って挿入させることを想定しています。

  1. func setup(_ view: UIView) {
  2. contentView.addSubview(view)
  3. view.snp.makeConstraints {
  4. $0.edges.equalTo(contentView)
  5. }
  6. }



制約をセットする

scrollViewの制約は、通常通り親Viewに対して同じ大きさになるよう制約をセットします。
contentViewの制約は工夫が必要で、親Viewに対して横Centerの指定とleftに対してgreaterThanOrEqualToを指定します。
この2つの制約によりCenter表示が可能になります。
  1. private func setupConstraint() {
  2. scrollView.snp.makeConstraints {
  3. $0.edges.equalToSuperview()
  4. }
  5. contentView.snp.makeConstraints {
  6. $0.height.equalTo(scrollView.frameLayoutGuide)
  7. // 横幅より小さい場合は、Center
  8. // 横幅より大きい場合は、通常の左寄せ + スクロール
  9. $0.top.right.bottom.equalTo(scrollView.contentLayoutGuide)
  10. $0.left.equalTo(scrollView.contentLayoutGuide).priority(.low)
  11. $0.left.greaterThanOrEqualTo(scrollView.contentLayoutGuide)
  12. $0.centerX.greaterThanOrEqualToSuperview()
  13. }
  14. }


ScrollのContent領域が定まらないというLayoutのwarningが発生したため、次の制約を追加します。
  1. $0.left.equalTo(scrollView.contentLayoutGuide).priority(.low)



完成形のコード

上記の全てを組み合わせると、次のようなコードになります。
  1. final class HorizontalScrollView: UIView {
  2. private let scrollView = UIScrollView()
  3. private let contentView = UIView()
  4.  
  5. override init(frame: CGRect) {
  6. super.init(frame: frame)
  7. setupViews()
  8. setupConstraint()
  9. }
  10.  
  11. required init?(coder aDecoder: NSCoder) {
  12. super.init(coder: aDecoder)
  13. setupViews()
  14. setupConstraint()
  15. }
  16.  
  17. private func setupViews() {
  18. scrollView.addSubview(contentView)
  19. addSubview(scrollView)
  20. }
  21.  
  22. private func setupConstraint() {
  23. scrollView.snp.makeConstraints {
  24. $0.edges.equalToSuperview()
  25. }
  26. contentView.snp.makeConstraints {
  27. $0.height.equalTo(scrollView.frameLayoutGuide)
  28. // aligin center when content width < frame width
  29. // aligin left when content width > frame width
  30. $0.top.right.bottom.equalTo(scrollView.contentLayoutGuide)
  31. $0.left.equalTo(scrollView.contentLayoutGuide).priority(.low)
  32. $0.left.greaterThanOrEqualTo(scrollView.contentLayoutGuide)
  33. $0.centerX.greaterThanOrEqualToSuperview()
  34. }
  35. }
  36.  
  37. func setup(_ view: UIView) {
  38. contentView.addSubview(view)
  39. view.snp.makeConstraints {
  40. $0.edges.equalTo(contentView)
  41. }
  42. }
  43. }

0 件のコメント:

コメントを投稿