scrollview - content view - 1) image, 2) tab, 3) stack view
Above is my storyboard arrangement. The tabs are actually collection view. Below the tab, there is stack view (which also inside the content view). When I click each of the tabs, I send the index of selected tab at didSelect. It will call the refreshData function which have this flow: The current subviews inside the stack view will be removed (using vc.mainStack.subviews.forEach({ $0.removeFromSuperview() })) and will reload another subviews according to the index of the selected tab. The position of the image will remain the same, which is at the top of the page. However, every time I click the tab, the screen will always scroll to top. How can I keep the scroll position (before I click another tab) so that when I click new tab, it will remain on the same scroll position?
self.yContentOffset = scrollView.contentOffset.y
already add above code inside scrollViewDidScroll and
vc.scrollView.contentOffset.y = self.yContentOffset
add above code after remove all subviews in the stack, then i call the new data(for subviews). Also tried adding the code after calling the new subviews, but both doesn't work. Do anyone knows the logic on how to do this?
Sounds like the issue is that the UI is being "refreshed" between the point where you remove the current subviews and when you add the new subviews. So your mainStack
becomes very short, resulting in the content view not being tall enough to require scrolling, and your scroll view adjusts itself accordingly.
Your options are to either wait remove the subviews until you have your new subviews, and remove / add in the same func, or replace the subviews with a clear "placeholder" view.
The second option could look like this:
func replaceViewsWithPlaceholderView() -> Void {
// get an array of the current views in the stack
let viewsToRemove = mainStack.arrangedSubviews
// create a clear view
let v = UIView()
v.translatesAutoresizingMaskIntoConstraints = false
v.backgroundColor = .clear
// needs a width
v.widthAnchor.constraint(equalToConstant: 1).isActive = true
// constrain the height of the "place holder" view to the current height of the stack view
v.heightAnchor.constraint(equalToConstant: mainStack.frame.height).isActive = true
// add the "place holder" view to the stack
mainStack.addArrangedSubview(v)
// remove the views that were in the stack
viewsToRemove.forEach {
$0.removeFromSuperview()
}
}
Then in your func that adds new subviews based on the selected tab, first:
// remove the "place holder" view
mainStack.arrangedSubviews.forEach {
$0.removeFromSuperview()
}
followed by (probably a .forEach
loop) adding the new subviews to main.Stack
.
Of course, if you have scrolled so your "tabs" are at the top of the scroll view, and "tab B" doesn't have enough subviews to require scrolling, the scroll view will again adjust - but only to the point where the bottom of the content view is at the bottom of the scroll view.