0

I am running Xcode 11 and would like to be able to change the background color of a UIScrollView as it moves from page to page in a 6 page setup. I have been able to change the label content for each page but the background color 'skips' to the last in the color array.

The arrays:

let stringArray = ["<- Swipe to begin", "Welcome", "Info", "more info", "more info 2", "end"]

let backgroundColorArray = [UIColor.orange, UIColor.blue, UIColor.red, UIColor.white, UIColor.green, UIColor.purple]

Then the scrollview content

func setupScrollView() {
    scrollView.delegate = self
    scrollView.contentSize = CGSize(width: self.view.frame.size.width * 6, height: scrollView.frame.size.height)

    for k in 0 ... 5 {
        scrollView.backgroundColor = backgroundColorArray[k]
    }

    for i in 0 ... 5 {
        let label = UILabel(frame: CGRect(x: scrollView.center.x + CGFloat(i) * self.view.frame.size.width - 130, y: 50, width: 260, height: 30))
        label.font = UIFont.boldSystemFont(ofSize: 26)
        label.textAlignment = .center
        label.text = stringArray[i]

        scrollView.addSubview(label)
    }
}

The scrollview background color changes to purple but does not change from page to page. What is the correct way to have the colors change?

rmaddy
  • 314,917
  • 42
  • 532
  • 579
forrest
  • 10,570
  • 25
  • 70
  • 132

1 Answers1

2

When you are calling

for k in 0 ... 5 {
    scrollView.backgroundColor = backgroundColorArray[k]
}

you are looping through each color in backgroundColorArray and updating the value. Because .purple is the last element in your backgroundColorArray, your scroll view, at the end of this for loop, is being set to purple. Your for loop is essentially doing the same thing as scrollView.backgroundColor = backgroundColorArray[5].

Now, what I suggest you do is implement UIScrollViewDelegate methods. You could implement scrollViewDidScroll(scrollView:). This is called every time the scroll view's content offset changes. What you could then do is set a switch statement that checks the content offset of your scroll view, and assigns the color accordingly:

extension MyViewController: UIScrollViewDelegate {
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        //Assuming your pages are situated horizontally from one another
        let page = scrollView.contentOffset.x / view.frame.width
        if page < 1 {
            scrollView.backgroundColor = backgroundColorArray[0]
        } else if page > 1 && page < 2 {
            scrollView.backgroundColor = backgroundColorArray[1]
        } else if page > 2 && page < 3 {
            scrollView.backgroundColor = backgroundColorArray[2]
        } else if page > 3 && page < 4 {
            scrollView.backgroundColor = backgroundColorArray[3]
        } else if page > 4 && page < 5 {
            scrollView.backgroundColor = backgroundColorArray[4]
        } else if page > 5 && page < 6 {
            scrollView.backgroundColor = backgroundColorArray[5]
        }
    }
}

You could also interpolate between colors depending on your scroll view's content offset. Here is a UIColor extension I use to do this:

extension UIColor {
    static func interpolate(from fromColor: UIColor, to toColor: UIColor, with progress: CGFloat) -> UIColor {
        let fromComponents = fromColor.components
        let toComponents = toColor.components

        let r = (1 - progress) * fromComponents.r + progress * toComponents.r
        let g = (1 - progress) * fromComponents.g + progress * toComponents.g
        let b = (1 - progress) * fromComponents.b + progress * toComponents.b
        let a = (1 - progress) * fromComponents.a + progress * toComponents.a

        return UIColor(red: r, green: g, blue: b, alpha: a)
    }
}

However I highly suggest you take a look at UIPageViewController. It sounds like it does more of what you are trying to manually do yourself. Check out this question I asked recently: Pan (not swipe) between view controllers

David Chopin
  • 2,780
  • 2
  • 19
  • 40
  • I actually started with PageView but it doesn't work for this project because I am integrating Lottie. The above code never gets called, so I can't really tell if it is working or not. – forrest Sep 25 '19 at 22:25
  • Sorry, try replacing `scrollViewDidScroll(scrollView: UIScrollView!)` with `scrollViewDidScroll(_ scrollView: UIScrollView)`. Assuming you've set your scroll view's delegate to your view controller (which it seems you have) and extended your view controller as a UIScrollViewDelegate and implemented this delegate method, it should be called every time the scroll view "scrolls". – David Chopin Sep 25 '19 at 22:27
  • That made the difference. Thank you. – forrest Sep 25 '19 at 22:30
  • Not a problem. Do you mind DMing me at some point why Lottie doesn't work with UIPageViewController? I just made a tinder-like application that utilizes a side-scrolling UIPageViewController, and feel I may be able to help. Or at least share some useful code. – David Chopin Sep 25 '19 at 22:31
  • 1
    Be happy to. I'll connect on LinkedIn. – forrest Sep 25 '19 at 22:40