Search code examples
swiftuiscrollviewconstraints

Add views horizontally to UIScrollView programmatically


I'm trying to stack three identical imageviews next to each other. The images are larger than the screen and I want to be able to scroll to the right, seeing a repetition of the image three times if I get to the end. The views keep stacking on top of each other rather than next to each other. I can't figure out what I'm doing wrong. Any help will be appreciated.

Here's my code:

func stackThreeImagesHorizontallyToScrollView(imageToStack :UIImage, scrollView: UIScrollView){
           
    var previousAnchor = scrollView.contentLayoutGuide.leadingAnchor

    for i in 0 ..< 3 {
        let imageViewToStack = UIImageView(image: imageToStack)
        
        switch i {
                    case 0:
                        imageViewToStack.backgroundColor = UIColor.green
                        break
                    case 1:
                        imageViewToStack.backgroundColor = UIColor.purple
                        break
                    case 2:
                        imageViewToStack.backgroundColor = UIColor.yellow
                        break

                    default: break

                    }
        
        scrollView.addSubview(imageViewToStack)

        NSLayoutConstraint.activate([
            imageViewToStack.leadingAnchor.constraint(equalTo: previousAnchor, constant: 0),
            imageViewToStack.heightAnchor.constraint(equalToConstant: imageToStack.size.height),
            imageViewToStack.widthAnchor.constraint(equalToConstant: imageToStack.size.width),
            imageViewToStack.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 0),
            imageViewToStack.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor, constant: 0),
            imageViewToStack.trailingAnchor.constraint(equalTo: imageViewToStack.leadingAnchor, constant: imageToStack.size.width)
        ])
        
        previousAnchor = imageViewToStack.trailingAnchor
    }
    
    previousAnchor.constraint(equalTo: scrollView.trailingAnchor, constant: 0).isActive = true
    
}

Solution

  • You forgot to set the translatesAutoresizingMaskIntoConstraints property of imageViewToStack to false:

    func stackThreeImagesHorizontallyToScrollView(imageToStack: UIImage, scrollView: UIScrollView) {
    
            var previousAnchor = scrollView.contentLayoutGuide.leadingAnchor
    
            for i in 0 ..< 3 {
                let imageViewToStack = UIImageView(image: imageToStack)
    
                /// ADD THIS LINE
                imageViewToStack.translatesAutoresizingMaskIntoConstraints = false
    
                switch i {
                case 0:
                    imageViewToStack.backgroundColor = UIColor.green
                    break
                case 1:
                    imageViewToStack.backgroundColor = UIColor.purple
                    break
                case 2:
                    imageViewToStack.backgroundColor = UIColor.yellow
                    break
    
                default: break
    
                }
    
                scrollView.addSubview(imageViewToStack)
    
                NSLayoutConstraint.activate([
                    imageViewToStack.leadingAnchor.constraint(equalTo: previousAnchor, constant: 0),
                    imageViewToStack.heightAnchor.constraint(equalToConstant: imageToStack.size.height),
                    imageViewToStack.widthAnchor.constraint(equalToConstant: imageToStack.size.width),
                    imageViewToStack.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 0),
                    imageViewToStack.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor, constant: 0),
                    imageViewToStack.trailingAnchor.constraint(equalTo: imageViewToStack.leadingAnchor, constant: imageToStack.size.width)
                ])
    
                previousAnchor = imageViewToStack.trailingAnchor
            }
    
            previousAnchor.constraint(equalTo: scrollView.trailingAnchor, constant: 0).isActive = true
    
        }