问题
My VC starts with stackView
attached with Align Bottom to Safe Area
.
I have tabBar, but in the beginning is hidden tabBar.isHidden = true
.
Later when the tabBar appears, it hides the stackView
So I need function that refresh constraints after tabBar.isHidden = false
When I start the app with tabBar.isHidden = false
the stackView
is shown properly.
Tried with every function like: stackView.needsUpdateConstraints() , updateConstraints() , setNeedsUpdateConstraints()
without success.
Now I'm changing the bottom programatically, but when I switch the tabBarIndex and return to that one with changed bottom constraints it detects the tabBar and lifts the stackView under another view (which is not attached with constraints). Like is refreshing again the constraints. I'm hiding and showing this stackView with constrains on/off screen.
I need to refresh constraints after tabBar.isHidden = false, but the constraints don't detect the appearance of the tabBar.
As I mention switching between tabBars fixes the issue, so some code executes to detecting tabBar after the switch. Is anyone know this code? I tried with calling the methods viewDidLayoutSubviews and viewWillLayoutSubviews without success... Any suggestions?
回答1:
tabBarController!.selectedIndex = 1
tabBarController!.selectedIndex = 0
This amateur approach fixed my bug... :D
回答2:
If you want to update view's layout, you can try layoutIfNeeded() function.
回答3:
after updating stackView constraints call this method:
stackView.superview?.layoutIfNeeded()
回答4:
Apple's Human Interface Guidelines
indicate that one should not mess around with the Tab Bar, which is why (I'm guessing) setting tabBar.isHidden
doesn't properly update the rest of the view hierarchy.
Quick searching comes up with various UITabBarController
extensions for showing / hiding the tab bar... but they all appear to push the tabBar down off-screen, rather than setting its .isHidden
property. May or may not be suitable for your use.
I'm assuming from your comments that your VC in tab index 0 has a button (or some other action) to show / hide the tabBar?
If so, here is an approach that may do the job....
Add this enum
in your project:
enum TabBarState {
case toggle, show, hide
}
and put this func in that view controller:
func showOrHideTabBar(state: TabBarState? = .toggle) {
if let tbc = self.tabBarController {
let b: Bool = (state == .toggle) ? !tbc.tabBar.isHidden : state == .hide
guard b != tbc.tabBar.isHidden else {
return
}
tbc.tabBar.isHidden = b
view.frame.size.height -= 0.1
view.setNeedsLayout()
view.frame.size.height += 0.1
}
}
You can call it with:
// default: toggles isHidden
showOrHideTabBar()
// toggles isHidden
showOrHideTabBar(state: .toggle)
// SHOW tabBar (if it's hidden)
showOrHideTabBar(state: .show)
// HIDE tabBar (if it's showing)
showOrHideTabBar(state: .hide)
I would expect that simply pairing .setNeedsLayout()
with .layoutIfNeeded()
after setting the tabBar's .isHidden
property should do the job, but apparently not.
The quick frame height change (combined with .setNeedsLayout()
) does trigger auto-layout, though, and the height change is not visible.
NOTE: This is the result of very brief testing, on one device and one iOS version. I expect it will work across devices and versions, but I have not done complete testing.
来源:https://stackoverflow.com/questions/60526419/swift-programmatically-refresh-constraints