##参考記事に制約をつける
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
}
}
}
##終わりに
もっといい方法あるはずw
誰かの参考になれば幸いです
Qiitaさんいつもお世話になってるので感謝
間違えてるところ等ありましたら教えてくださいー
##参考
https://qiita.com/ynakaDream/items/960899183c38949c2ab0