Home > Software design >  How to scroll to the View Controller top and display a Large Title?
How to scroll to the View Controller top and display a Large Title?

Time:09-03

I have a ViewControllerOne with a tableView constrained to a superview and filled with a content. User can scroll down some content, then switch to ViewControllerTwo and change tableView data source content on another.

When that happens and user returns to the ViewControllerOne I want the VC to be reset on its initial state at the top with a Large Title and a new content, but with a workaround I found it scrolls only till the tableView top and stops on a Small Title.

Here is the code:

  1. When user picks a new Data Source in ViewControllerTwo I save it as a bool in UserDefaults:

      UserDefaults.standard.set(true, forKey: "newDataSourcePicked")
    
  2. In ViewControllerOne I trigger the scrolling method in a viewWillAppear():

       override func viewWillAppear(_ animated: Bool) {
          super.viewWillAppear(animated)
           scrollVCUp()
       }
    
  3. Here is scrollVCUp(). Here I use the saved bool. Also use delay because its not scrolling without it:

     func scrollVCUp() {
     if newDataSourcePicked {
         traitCollection.verticalSizeClass == .compact ? setVCOffset(with: view.safeAreaInsets.top, and: updateLabelTopInset, delayValue: 0.1) : setVCOffset(with: biggestTopSafeAreaInset, and: updateLabelTopInset, delayValue: 0.1)
         UserDefaults.standard.set(false, forKey: "newDataSourcePicked")
     }
    }
    
  4. Here is setVCOffset():

     func setVCOffset(with viewInset: CGFloat, and labelInset: CGFloat, delayValue: Double = 0.0) {
        let firstVC = navigationController?.viewControllers.first as? CurrencyViewController
        guard let scrollView = firstVC?.view.subviews.first(where: { $0 is UIScrollView }) as? UIScrollView else { return }
    
     if delayValue > 0.0 {
         DispatchQueue.main.asyncAfter(deadline: .now()   delayValue) {
             scrollView.setContentOffset(CGPoint(x: 0, y: -(viewInset - labelInset)), animated: true)
         }
     } else {
         scrollView.setContentOffset(CGPoint(x: 0, y: -(viewInset - labelInset)), animated: true)
     }
     }
    

I also have a tabBar and when I use the same code to scroll ViewControllerOne by tapping on a tabBar it scrolls and shows a Large Title, but doesn't work if we switch to another VC and back.

Here is a gif:

What should I do to scroll and always show a Large Title?

CodePudding user response:

Try instead of using

scrollView.setContentOffset(CGPoint(x: 0, y: -(viewInset - labelInset)), animated: true)

I think you should use

scrollView.setContentOffset(.zero, animated: true)

CodePudding user response:

Didn't find any reasonable explanation for my case, but repeating the same code with a little delay one more time fix the issue and after the second code run Large Title appears on scroll.

    func scrollVCUp() {
    if needToScrollUpViewController {
        traitCollection.verticalSizeClass == .compact ? setVCOffset(with: view.safeAreaInsets.top, and: updateLabelTopInset, delayValue: 0.01) : setVCOffset(with: biggestTopSafeAreaInset, and: updateLabelTopInset, delayValue: 0.01)
        traitCollection.verticalSizeClass == .compact ? setVCOffset(with: view.safeAreaInsets.top, and: updateLabelTopInset, delayValue: 0.40) : setVCOffset(with: biggestTopSafeAreaInset, and: updateLabelTopInset, delayValue: 0.40)
    }
}
  • Related