skip to Main Content

How to make UIView which is inside scrollview adapt to screen orientation when user changes screen from portrait to landscape in swift?

var scrollView: UIScrollView = {
    var scroll = UIScrollView()
    scroll.translatesAutoresizingMaskIntoConstraints = false
      
    return scroll
}()

view.addSubview(scrollView)

scrollView.topAnchor.constraint(equalTo: view.topAnchor, constant: 100).isActive = true
scrollView.centerXAnchor.constraint(equalTo: view.centerXAnchor, constant: 0).isActive = true
scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0).isActive = true
scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 0).isActive = true
scrollView.heightAnchor.constraint(equalToConstant: 500).isActive = true

for i in 0..<arr.count {
    var contentView = UIView()
    contentView.frame = CGRect(x: i * Int(view.bounds.size.width) + 10, y: 0, width: Int(view.bounds.size.width) - 20 , height: Int(view.frame.height))

    scrollView.contentSize = CGSize(width: (view.frame.size.width * CGFloat((Double(i)+1))) ,height: scrollView.frame.size.height) 
}

Image

2

Answers


  1. You really want to be using auto-layout instead of trying to calculate frame sizes. Let it do all the work for you.

    Based on your code, it looks like you want each "contentView" to be the width of the scrollView’s frame, minus 20 (so you have 10-pts of space on each side).

    You can quite easily do this by embedding your contentViews in a UIStackView.

    Here’s a simple example:

    class ViewController: UIViewController {
        
        var scrollView: UIScrollView = {
            var scroll = UIScrollView()
            scroll.translatesAutoresizingMaskIntoConstraints = false
            
            return scroll
        }()
        
        override func viewDidLoad() {
            super.viewDidLoad()
    
            view.addSubview(scrollView)
            
            // use a stack view to hold and arrange the scrollView's subviews
            let stackView = UIStackView()
            stackView.translatesAutoresizingMaskIntoConstraints = false
            stackView.spacing = 20
    
            // add the stackView to the scrollView
            scrollView.addSubview(stackView)
    
            // respect safe area
            let safeG = view.safeAreaLayoutGuide
            
            // use scrollView's Content Layout Guide to define scrollable content
            let layoutG = scrollView.contentLayoutGuide
    
            // use scrollView's Frame Layout Guide to define content height (since you want horizontal scrolling)
            let frameG = scrollView.frameLayoutGuide
    
            NSLayoutConstraint.activate([
                
                scrollView.topAnchor.constraint(equalTo: safeG.topAnchor, constant: 100),
                
                // you're setting leading and trailing, so no need for centerX
                //scrollView.centerXAnchor.constraint(equalTo: view.centerXAnchor, constant: 0),
                
                scrollView.leadingAnchor.constraint(equalTo: safeG.leadingAnchor, constant: 0),
                scrollView.trailingAnchor.constraint(equalTo: safeG.trailingAnchor, constant: 0),
                
                // let's constrain the scrollView bottom to the view (safe area) bottom
                //scrollView.heightAnchor.constraint(equalToConstant: 500),
                scrollView.bottomAnchor.constraint(equalTo: safeG.bottomAnchor, constant: -10.0),
                
                // constrain Top and Bottom of the stackView to scrollView's Content Layout Guide
                stackView.topAnchor.constraint(equalTo: layoutG.topAnchor),
                stackView.bottomAnchor.constraint(equalTo: layoutG.bottomAnchor),
                
                // 10-pts space on leading and trailing
                stackView.leadingAnchor.constraint(equalTo: layoutG.leadingAnchor, constant: 10.0),
                stackView.trailingAnchor.constraint(equalTo: layoutG.trailingAnchor, constant: -10.0),
                
                // constrain stackView's height to scrollView's Frame Layout Guide height
                stackView.heightAnchor.constraint(equalTo: frameG.heightAnchor),
                
            ])
            
            // add some views to the stack view
            let arr: [UIColor] = [
                .red, .green, .blue, .yellow, .purple,
            ]
            
            for i in 0..<arr.count {
                let contentView = UIView()
                contentView.backgroundColor = arr[i]
                stackView.addArrangedSubview(contentView)
                
                // constrain each "contentView" width to scrollView's Frame Layout Guide width minus 20
                contentView.widthAnchor.constraint(equalTo: frameG.widthAnchor, constant: -20).isActive = true
                
                // don't do this
                //contentView.frame = CGRect(x: i * Int(view.bounds.size.width) + 10, y: 0, width: Int(view.bounds.size.width) - 20 , height: Int(view.frame.height))
                
                // don't do this
                //scrollView.contentSize = CGSize(width: (view.frame.size.width * CGFloat((Double(i)+1))) ,height: scrollView.frame.size.height)
                
            }
    
        }
    
    }
    

    Run that and see if that’s what you’re going for.

    Login or Signup to reply.
  2. You need to add your subviews to the scroll view and setup their constraints – using of an auto-layout. Don’t use contentView.frame = CGRect(…) and scrollView.contentSize = CGSize(…).

    For example you can change your for-in to this:

    Note: this is only example, change your for-in loop to your needs.

    for i in 0..<arr.count {
    
        // we need to distinguish the first and last subviews (because different constraints)
        let topAnchor = i == 0 ? scrollView.topAnchor : scrollView.subviews.last!
        let isLast = i == arr.count - 1
    
        // here we will use a specific height for all subviews except the last one
        let subviewHeight = 60
    
        var contentView = UIView()
        contentView.translatesAutoresizingMaskIntoConstraints = false
        scrollView.addSubview(contentView)
        
        if isLast {
            NSLayoutConstraint.activate([
                contentView.topAnchor.constraint(equalTo: topAnchor),
                contentView.widthAnchor.constraint(equalTo: scrollView.widthAnchor),
                contentView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),
                contentView.centerXAnchor.constraint(equalTo: scrollView.centerXAnchor)
           ]
        } else {
            NSLayoutConstraint.activate([
                contentView.topAnchor.constraint(equalTo: topAnchor),
                contentView.widthAnchor.constraint(equalTo: scrollView.widthAnchor),
                contentView.heightAnchor.constraint(equalToConstant: subviewHeight),
                contentView.centerXAnchor.constraint(equalTo: scrollView.centerXAnchor)
           ]
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search