[Reproduced] An example of a ScrollView

//
//  ViewController.swift
//  AutolayoutScrollViewInCode
//
// Created by Zhang Xingyu on 15/12/21.
// Copyright © 2015 Zhang Xingyu. All rights reserved.
//

import UIKit
import SnapKit

let ScreenWidth = UIScreen.mainScreen().bounds.width
let ScreenHeight = UIScreen.mainScreen().bounds.height
let topScrollHeight: CGFloat = UIScreen.mainScreen().bounds.height / 3
let boxWidth: CGFloat = ScreenWidth * 2 / 3
let boxGap: CGFloat = 20

class ViewController: UIViewController {
    
    let scrollView = UIScrollView()
    let containerView = UIView()

    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        /**
        Layout with Container
        Use container in scrollview to layout subviews
        */
        
        /**
        Layout with external views
        Use views outside to locate subviews in scrollview
        */
        layoutWithContainer()
//        layoutWithAbsoluteView()
//        layoutWithCustomePageSize()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    override func viewDidLayoutSubviews() {
//        scrollView.contentSize = CGSizeMake(1000, topScrollHeight)
//        scrollView.contentSize.width = 1000
        print(scrollView.contentSize.width)
    }
}

// MARK: - Auto Layout with Container
extension ViewController {
    func layoutWithContainer() {
        scrollView.bounces = false
        view.addSubview(scrollView)
        scrollView.backgroundColor = UIColor.yellowColor()
        scrollView.addSubview(containerView)
        
        containerView.backgroundColor = scrollView.backgroundColor
        
        /**
        * Add constraints to scrollView
        *  Add constraints to scrollView
        */
        scrollView.snp_makeConstraints { (make) -> Void in
            make.centerY.equalTo(view.snp_centerY)
            make.left.right.equalTo(view)
            make.height.equalTo(topScrollHeight)
        }
        
        /**
        * Add constraints to the containerView, then just determine the width of the containerView
        *  Add constraints to containerView, the only thing we will do
        *  is to define the width of containerView
        */
        containerView.snp_makeConstraints { (make) -> Void in
            make.edges.equalTo(scrollView)
            make.height.equalTo(topScrollHeight)
        }
        
        for i in 0...5 {
            let box = UIView()
            box.backgroundColor = UIColor.redColor()
            containerView.addSubview(box)
            
            box.snp_makeConstraints(closure: { (make) -> Void in
                make.top.height.equalTo(containerView) // After determining the top and height, the box is completely determined in the vertical direction
                make.width.equalTo(boxWidth)
                if i == 0 {
                    make.left.equalTo(containerView).offset(boxGap / 2)
                }
                else if let previousBox = containerView.subviews[i - 1] as? UIView{
                    make.left.equalTo(previousBox.snp_right).offset(boxGap)
                }
                if i == 5 {
                    containerView.snp_makeConstraints(closure: { (make) -> Void in
                        // This step is the key, it determines the width of the container, which also determines the contentSize
                        // This step is very important, it set the width of container, so the
                        // contentSize is available now
                        make.right.equalTo(box)
                    })
                }
            })
        }
    }
}

extension ViewController {
    func layoutWithAbsoluteView() {
        scrollView.bounces = false
        view.addSubview(scrollView)
        scrollView.backgroundColor = UIColor.yellowColor()
        
        scrollView.snp_makeConstraints { (make) -> Void in
            make.centerY.equalTo(view.snp_centerY)
            make.left.right.equalTo(view)
            make.height.equalTo(topScrollHeight)
        }
        
        for i in 0...5 {
            let box = UIView()
            box.backgroundColor = UIColor.redColor()
            scrollView.addSubview(box)
            
            // box depends on external view layout and cannot depend on scrollView
            // The position of box rely on self.view instead of scrollView
            box.snp_makeConstraints(closure: { (make) -> Void in
                make.top.equalTo(0)
                // This bottom can be incorret when device is rotated
                make.bottom.equalTo(view).offset(-(ScreenHeight - topScrollHeight) / 2)
                make.height.equalTo(topScrollHeight)
                
                make.width.equalTo(boxWidth)
                if i == 0 {
                    make.left.equalTo(boxGap / 2)
                }
                else if let previousBox = scrollView.subviews[i - 1] as? UIView{
                    make.left.equalTo(previousBox.snp_right).offset(boxGap)
                }
                
                if i == 5 {
                    // Set the rightmost box here, the distance from the right border of contentSize
                    // The the distance from the box on the right side
                    // to the right side of contentSize
                    make.right.equalTo(scrollView)
                }
            })
        }
    }
}

// MARK: - Auto Layout with Container
extension ViewController {
    /**
     The key is to set clipsToBounds to false and make the width of frame of scrollview less than the width of screen.
     Usually the width now is padding + subviewWidth
     The key is that clipsToBounds is set to no, the width of scrollview itself is smaller than the screen width, generally set to padding + subview width
     */
    func layoutWithCustomePageSize() {
        scrollView.bounces = false
        view.addSubview(scrollView)
        scrollView.pagingEnabled = true
        scrollView.clipsToBounds = false   // *important!* //
        scrollView.backgroundColor = UIColor.yellowColor()
        scrollView.addSubview(containerView)
        
        containerView.backgroundColor = scrollView.backgroundColor
        
        /**
        * Add constraints to scrollView
        *  Add constraints to scrollView
        */
        scrollView.snp_makeConstraints { (make) -> Void in
            make.center.equalTo(view.snp_center)
            make.width.equalTo(boxWidth + boxGap)   // *important!* //
            make.height.equalTo(topScrollHeight)
        }
        
        /**
        * Add constraints to the containerView, then just determine the width of the containerView
        *  Add constraints to containerView, the only thing we will do
        *  is to define the width of containerView
        */
        containerView.snp_makeConstraints { (make) -> Void in
            make.edges.equalTo(scrollView)
            make.height.equalTo(topScrollHeight)
        }
        
        for i in 0...40 {
            let box = UIView()
            box.backgroundColor = UIColor.redColor()
            containerView.addSubview(box)
            
            box.snp_makeConstraints(closure: { (make) -> Void in
                make.top.height.equalTo(containerView) // After determining the top and height, the box is completely determined in the vertical direction
                make.width.equalTo(boxWidth)
                if i == 0 {
                    make.left.equalTo(containerView).offset(boxGap / 2)
                }
                else if let previousBox = containerView.subviews[i - 1] as? UIView{
                    make.left.equalTo(previousBox.snp_right).offset(boxGap)
                }
                if i == 40 {
                    containerView.snp_makeConstraints(closure: { (make) -> Void in
                        // This step is the key, it determines the width of the container, which also determines the contentSize
                        // This step is very important, it set the width of container, so the
                        // contentSize is available now
                        make.right.equalTo(box).offset(boxGap / 2)
                    })
                }
            })
        }
    }
}

 

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326896726&siteId=291194637