UIProgressView 在应用从后台返回时不会重新绘制其框架。

huangapple go评论57阅读模式
英文:

UIProgressView do not redraw his frame when app launch back from background

问题

I have view with UIProgressView and 3 dot-view. It's like a page control. Each page - the video. progressView displays progress of video playback.

Ok. I do not use constraints for left and right anchors because my progressView should swap places with dot-view. For example, when the current video is ended and the next starts playing, we should swap positions of progressView with the next dot-view. To swap, I just change frames.

The problem is that when I move the app to the background and then return, my progressView loses its old frame. It attaches to the left side because .frame.minX is 0.

And the last problem: this issue occurs only after the first return from the background.

What I tried to do:

  • Save progressView frames before the app goes to the background and restore them when the app comes to the foreground: progressView.frame = progressViewOldFrames and call setNeedsDisplay().
  • Add a constraint to the leftAnchor with a constant (frame.minX) before going to the background and remove it after coming to the foreground.
  • Combine these two approaches.

So now it looks like:

func appWillMoveInBackground() {
    progressBarXConstraint = progressBar.leftAnchor.constraint(equalTo: self.leftAnchor, constant: progressBar.frame.minX)
    progressBarXConstraint?.isActive = true
    progressBarFrame = progressBar.frame
}

func updateProgressWidth() {
    progressBarXConstraint?.isActive = false
    // Here, I use constraints because my width and height also change,
    // and only constraints help me.
    progressBar.widthAnchor.constraint(equalToConstant: 32).isActive = true
    progressBar.heightAnchor.constraint(equalToConstant: 6).isActive = true
    progressBar.frame = progressBarFrame
    progressBar.setNeedsDisplay()
}

UPDATE:

Okay, I should explain more. I guess I can't use constraints because there is some animation while scrolling. When we scroll to the right, we should move our progressView to some points on the right. And at that moment, we should move the right dot-view to the left. I mean, we do not scroll page by page; we can scroll to halfway on the right, then we can return to the initial position.

This code block changes the frames of progressView and dot-view. The exact formulas are not important. Please try to understand the behavior of this view:

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    // Calculate some mathematical variables
    // and call a method that makes changes in frames
    pageControl.moveBetweenPages(atPercentValue: distInPercents - 100)
}

// It's part of the body of the moveBetweenPages() function
progressBar.frame = CGRect(x: progStartX + progAddDist, y: 0,
                           width: SizeConstants.progressBarWidth.value,
                           height: SizeConstants.height.value)

let dotStartX: CGFloat = SizeConstants.progressBarWidth.value + SizeConstants.itemsSpacing.value + (CGFloat(currentPageNum) * dotSectionSize)
dots[currentPageNum].view.frame = CGRect(x: dotStartX - dotAddDist, y: 0,
                                         width: SizeConstants.dotWidth.value,
                                         height: SizeConstants.height.value)

Images show how it looks before going to the background and after:

UIProgressView 在应用从后台返回时不会重新绘制其框架。

英文:

<br>
i have view with UIProgressView and 3 dot-view. It's like a page control. Each page - the video. progressView displays progress of video playback
<br>
ok. I do not use constraints for left and right anchors, because my progressView should swap places with dot-view. For example, when current video is ended and next start play, we should swap positions of progressView with next dot-view. For swap i just change frames
<br>
and the problem is: when i move app to background and returns back, my progressView loses his old frame. It attaches to the left side, because .frame.minX is 0
<br>
and the last one: this problem occurs only after first returns from background
<br>
what i tried to do:

  • save progressView frames before app is going to background and restore it when app comes to foreground: progressView.frame = progressViewOldFrames and call setNeedsDisplay()
  • add constraint to leftAnchor with constant (frame.minX) before background and remove it after foreground
  • combine these 2 tries

so now it looks like

func appWillMoveInBackground() {
    progressBarXConstraint = progressBar.leftAnchor.constraint(equalTo: self.leftAnchor, constant: progressBar.frame.minX)
    progressBarXConstraint?.isActive = true
    progressBarFrame = progressBar.frame
}

func updateProgressWidth() {
    progressBarXConstraint?.isActive = false
    // here i use constraints because my width and height also disables
    // and only constraints helps me
    progressBar.widthAnchor.constraint(equalToConstant: 32).isActive = true
    progressBar.heightAnchor.constraint(equalToConstant: 6).isActive = true
    progressBar.frame = progressBarFrame
    progressBar.setNeedsDisplay()
}

UPDATE
ok, i should explain more. I guess i cant use constraints because we have some animation while we are scrolling. When we scroll to right - we should move our progressView to some points at right. And in this moment we should move right dot-view to the left. I mean, we do not scroll page by page, we can scroll to a half on the right, then we can return to the initial position.
<br>
this code of block did change frames of progressView and dot-view. Formulas are not important. Please, just understand the behavior of this view

func scrollViewDidScroll(_ scrollView: UIScrollView) {
   // calc some math variables
   // and call method that make changes in frames
   pageControl.moveBetweenPages(atPercentValue: distInPercents - 100)
}

// its part of body moveBetweenPages() func
progressBar.frame = CGRect(x: progStartX + progAddDist, y: 0,
                           width: SizeConstants.progressBarWidth.value,
                           height: SizeConstants.height.value)

let dotStartX: CGFloat = SizeConstants.progressBarWidth.value + SizeConstants.itemsSpacing.value + (CGFloat(currentPageNum) * dotSectionSize)
dots[currentPageNum].view.frame = CGRect(x: dotStartX - dotAddDist, y: 0,
                                         width: SizeConstants.dotWidth.value,
                                         height: SizeConstants.height.value)

images shows how it looks before background and afterUIProgressView 在应用从后台返回时不会重新绘制其框架。

答案1

得分: 0

matt在评论中建议我使用constraints而不是frames,是的,这有帮助,而且有效。

唯一需要注意的是,在更新约束后不要忘记调用setNeedsLayout()

英文:

matt from comments suggested me use constraints instead of frames and yes, it helps and it works
<br>
only thing i can say is dont forget call setNeedsLayout() after constraints update

huangapple
  • 本文由 发表于 2023年2月19日 00:29:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/75494734.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定