0
0

More than 1 year has passed since last update.

自動で横スクロールするページに制約をつける

Posted at

参考記事に制約をつける

UIScrollViewにコードで制約をつける

import UIKit

final class ViewController: UIViewController {

    struct Photo {
        var imageName: String
    }
    //型のネスト  [ViewController.Photo]
    var photoList = [
        Photo(imageName: "gear"),
        Photo(imageName: "magnifyingglass"),
        Photo(imageName: "clock")
    ]

    private lazy var scrollView: UIScrollView = {
        let scrollView = UIScrollView()
        scrollView.showsVerticalScrollIndicator = false
        scrollView.translatesAutoresizingMaskIntoConstraints = false
        return scrollView
    }()


    private var pageControl: UIPageControl = {
        let pageControl = UIPageControl()
        pageControl.numberOfPages = 3
        pageControl.pageIndicatorTintColor = UIColor.lightGray
        pageControl.backgroundColor = .green
        pageControl.currentPageIndicatorTintColor = UIColor.black
        return pageControl
    }()

    private lazy var button: UIButton = {
        let button = UIButton()
        button.backgroundColor = .orange
        button.setTitle("戻る", for: .normal)
        button.tintColor = .white
        button.addTarget(self, action: #selector(didTapDone), for: .touchUpInside)
        return button
    }()

    private var offsetX: CGFloat = 0
    private var timer: Timer!

    //MARK: - ライフサイクル等
    override func viewDidLoad() {
        super.viewDidLoad()

        let frameGuide = scrollView.frameLayoutGuide

        scrollView.delegate = self
        scrollView.backgroundColor = .green

        view.addSubview(scrollView)

        view.addSubview(pageControl)

        frameGuide.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
        frameGuide.topAnchor.constraint(equalTo:  pageControl.bottomAnchor, constant: -5).isActive = true
        frameGuide.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
        frameGuide.bottomAnchor.constraint(equalTo: view.bottomAnchor,constant: -view.bounds.height / 4).isActive = true

        setUpImageView()

        pageControl.anchor(top: view.safeAreaLayoutGuide.topAnchor, leading: view.safeAreaLayoutGuide.leadingAnchor, bottom: nil, trailing: view.safeAreaLayoutGuide.trailingAnchor, padding: .init(top: 2, left: 0, bottom: 0, right: 0),size: .init(width: view.frame.size.width, height: 20))
        pageControl.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true

        view.addSubview(button)
        button.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        button.anchor(top: scrollView.bottomAnchor, leading: nil, bottom: nil, trailing: nil, padding: .init(top: 5, left:0 , bottom: 0, right: 0),size: .init(width:view.frame.size.width / 2, height: 50))
        // タイマーを作成
        self.timer = Timer.scheduledTimer(timeInterval: 3, target: self, selector: #selector(self.scrollPage), userInfo: nil, repeats: true)
    }

    // viewWillDisappearされたらタイマーが破棄される
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        if let workingTimer = self.timer {
            workingTimer.invalidate()
        }
    }

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        scrollView.isPagingEnabled = true
        scrollView.alwaysBounceHorizontal = true
 //scrollViewのサイズ指定
        scrollView.contentSize = CGSize(width: view.frame.size.width * 3, height: view.frame.size.height / 2)

    }

    //MARK: - 関数等
    @objc func didTapDone() {
        print("tapされたー")
    }


    // UIImageViewを生成
    func createImageView(x: CGFloat, y: CGFloat, width: CGFloat, height: CGFloat, image: Photo) -> UIImageView {
        let imageView = UIImageView(frame: CGRect(x: x, y: y, width: width, height: height))
        let image = UIImage(systemName:  image.imageName)
        imageView.image = image
        return imageView
    }

    // photoListの要素分UIImageViewをscrollViewに並べる
    func setUpImageView() {
        for i in 0 ..< self.photoList.count {
            let photoItem = self.photoList[i]
            let imageView = createImageView(x: 0, y: 0, width: self.scrollView.frame.size.width, height: self.scrollView.frame.size.height , image: photoItem)

            imageView.translatesAutoresizingMaskIntoConstraints = false
            imageView.backgroundColor = .gray

            scrollView.addSubview(imageView)
            //ここポイントview.frame.size.width * CGFloat(i) でスクロールするたびにcenterXAnchorをずらしてる
            imageView.centerXAnchor.constraint(equalTo: scrollView.centerXAnchor,constant: view.frame.size.width * CGFloat(i)).isActive = true
            imageView.centerYAnchor.constraint(equalTo: scrollView.centerYAnchor).isActive = true
            //大きさ等
            imageView.widthAnchor.constraint(equalTo: scrollView.widthAnchor,constant:  -20).isActive = true
            imageView.heightAnchor.constraint(equalTo: scrollView.heightAnchor,constant: -20).isActive = true
        }

    }

         // offsetXの値を更新することページを移動
    @objc func scrollPage() {
        // 画面の幅分offsetXを移動
        self.offsetX += self.view.frame.size.width
        // 3ページ目まで移動したら1ページ目まで戻る
        if self.offsetX < self.view.frame.size.width * 3 {
            UIView.animate(withDuration: 0.3) {
                self.scrollView.contentOffset.x = self.offsetX
            }
        } else {
            UIView.animate(withDuration: 0.3) {
                self.offsetX = 0
                self.scrollView.contentOffset.x = self.offsetX
            }
        }
    }

}


//MARK: - UIScrollViewDelegate
extension ViewController: UIScrollViewDelegate {
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        // scrollViewのページ移動に合わせてpageControlの表示も移動
        self.pageControl.currentPage = Int(self.scrollView.contentOffset.x / self.scrollView.frame.size.width)
        // offsetXの値を更新
        self.offsetX = self.scrollView.contentOffset.x
    }


}


UIViewの制約Extension

import UIKit

extension UIView {

    func anchor(top: NSLayoutYAxisAnchor?,
                leading: NSLayoutXAxisAnchor?,
                bottom: NSLayoutYAxisAnchor?,
                trailing: NSLayoutXAxisAnchor?,
                padding: UIEdgeInsets = .zero,
                size: CGSize = .zero) {
        translatesAutoresizingMaskIntoConstraints = false

        if let top = top {
            topAnchor.constraint(equalTo: top, constant: padding.top).isActive = true
        }

        if let leading = leading {
            leadingAnchor.constraint(equalTo: leading, constant: padding.left).isActive = true
        }

        if let bottom = bottom {
            bottomAnchor.constraint(equalTo: bottom, constant: -padding.bottom).isActive = true
        }

        if let trailing = trailing {
            trailingAnchor.constraint(equalTo: trailing, constant: -padding.right).isActive = true
        }

        if size.width != 0 {
            widthAnchor.constraint(equalToConstant: size.width).isActive = true
        }

        if size.height != 0 {
            heightAnchor.constraint(equalToConstant: size.height).isActive = true
        }
    }
}

完成イメージ

オートスクロール.gif

終わりに

もっといい方法あるはずw
誰かの参考になれば幸いです
Qiitaさんいつもお世話になってるので感謝
間違えてるところ等ありましたら教えてくださいー

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0