Search code examples
swiftswiftuitimercountdowntimerswiftui-animation

Fill entire screen with a color using Timer - SwiftUI


I am trying to use a timer and fill the screen with color. To put it simply: I am getting the screen height with \ (UIScreen.main.bounds.height) and divide it with selectedTime, let's say \ (120)seconds. Problem occurs here: the screen fills up with roundly 232, not 844.0 screen size and it fills up in 32 seconds instead of 120 seconds. I'm probably missing something. Relevant code section:

.onChange(of: secondsToMinutesAndSeconds(seconds: timerManager.secondsLeft), perform: { waveTime in
            
            let selectedCircularValue = availableMinutes[self.selectedCircularIndex] * 60
            let heightProgress = CGFloat(UIScreen.main.bounds.height / CGFloat(selectedCircularValue))
            if timerManager.screenHeightChanged < UIScreen.main.bounds.height {
                
                timerManager.screenHeightChanged += CGFloat(heightProgress)
                withAnimation(.linear) {
                    
                    self.colorSize = CGFloat(Double(timerManager.screenHeightChanged))
                }
            } else {
                timerManager.screenHeightChanged = 0
            }
        })

Progress output

 { seconds 120
        screenHeight 844.0
        estimatedTime screen / seconds -> (7.033333333333333)
        ...
        progress 14.066666666666666
        ...
        progress 225.06666666666663
        ...
        progress 232.09999999999997
        
        }

Finally, is it possible to make the animation smooth?

Mine

My expectation


Solution

  • UIScreen can be quite annoying in my experience. Try using GeometryReader instead, it works much better when dealing with SwiftUI views. Wrap the view like this

    GeometryReader { geo in
        SomeView()
    }
    .frame(width: .infinity, height: .infinity) //may not need this
    

    Then Whenever you want the size of the view just use geo.size.width or geo.size.height

    For the animation, use the withAnimation function in conjunction with a modifier like .animation(.linear).

    As you haven't shared a minimal reproducible example, I can't share a complete solution or test my solution for your case.