0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

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

Posted at

##参考記事に制約をつける
https://www.hfoasi8fje3.work/entry/2019/02/20/233607

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さんいつもお世話になってるので感謝
間違えてるところ等ありましたら教えてくださいー
##参考
https://qiita.com/ynakaDream/items/960899183c38949c2ab0

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?