我正试图将视图捕捉到UITabBarController的tabBar(UITabBar),从不隐藏它(Apple在tvOS App Store的’Featured’选项卡中的方式).
我可以通过在直接包含在UITabBarController中的UIViewController中设置约束来使其工作.当隐藏和显示标签栏时,视图(在我的例子中,是一个UICollectionView)完全跟随动画.但是当我的UIViewController在UINavigationController中时,它也不起作用.它最终更新,但是当UITabBar动画(隐藏和显示)时,它不会更新.
以下是我使用NSLayoutConstraints设置约束的方法:
UIView * targetView = self.collectionView;
NSLayoutConstraint *constraint1 = [NSLayoutConstraint constraintWithItem:targetView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.tabBarController.tabBar attribute:NSLayoutAttributeBottom multiplier:1 constant:0];
NSLayoutConstraint *constraint2 = [NSLayoutConstraint constraintWithItem:targetView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1 constant:0];
NSLayoutConstraint *constraint3 = [NSLayoutConstraint constraintWithItem:targetView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeHeight multiplier:1 constant:0];
NSLayoutConstraint *constraint4 = [NSLayoutConstraint constraintWithItem:targetView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeWidth multiplier:1 constant:0];
[self.view.window addConstraint:constraint1];
[self.view addConstraints:@[constraint2, constraint3, constraint4]];
这是我如何用Masonry设置相同的约束(两者都有相同的结果,但这更具可读性):
[self.containerView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.width.height.equalTo(self.view);
make.top.equalTo(self.tabBarController.tabBar.mas_bottom);
}];
这是一个展示我的问题的示例项目:
https://www.dropbox.com/s/bxbi0gyidxhu2bz/SampleMovingWithTabBar.zip?dl=1
这是一个错误还是预期的行为?
我正试图在另一个更复杂的应用程序中实现这个“视图不隐藏在标签栏下”的行为,我得到了同样奇怪的行为.虽然在这种情况下没有涉及UINavigationController.该视图直接位于UIViewController(它是UITabBarController的viewControllers数组的一部分)中.
什么可以阻止在动画期间遵守自动布局约束?
这是我的View Controller层次结构在我链接到的演示项目中的样子(UINavigationController中的View Controller是在显示/隐藏标签栏时没有动画的那个):
<UITabBarController 0x7fca42d10bb0>, state: appeared, view: <UILayoutContainerView 0x7fca42f848b0>
| <FirstViewController 0x7fca42d11340>, state: disappeared, view: <UIView 0x7fca42f96510>
| <UINavigationController 0x7fca43812000>, state: appeared, view: <UILayoutContainerView 0x7fca42d46200>
| | <FirstViewController 0x7fca42f347f0>, state: appeared, view: <UIView 0x7fca42f8bd90>
最佳答案 每当您在此时使用CoreAnimation API进行动画时,布局约束在瞬态动画期间不会受到约束.
当您使用NSLayoutconstraint的属性(如常量用于动画)时,自动布局会在瞬态动画期间遵循约束.
CoreAnimations API包括UIView的基于块的动画.如果您有兴趣进一步阅读,那么这里是wwdc video
但是,看看你的代码,我认为这不是你的问题.您希望在UITabbar动画时尊重布局约束.您只需要在viewDidLayoutSubviews中设置约束而不是videDidAppear,您应该使用现有代码进行设置.
编辑—
我得到了一些关于这个问题的更多细节.首先,这不是苹果的错误. UITabBar只负责它的直接子视图控制器.它没有关于它的子结构的任何信息.你有责任将这一责任归为一类.
解决这个问题的方法是监听UIViewController的转换调用并相应地设置动画.
这是神奇的代码.将其添加到视图控制器.
-(void)didUpdateFocusInContext:(UIFocusUpdateContext *)context withAnimationCoordinator:(UIFocusAnimationCoordinator *)coordinator{
NSString *prevFocusViewClassName = NSStringFromClass([context.previouslyFocusedView class]);
NSString *nextFocusedView = NSStringFromClass([context.nextFocusedView class]);
// The tabbar is going to disappear
if ([prevFocusViewClassName isEqualToString:kUITabBarButtonClassName] &&
![nextFocusedView isEqualToString:kUITabBarButtonClassName]) {
[self.view layoutIfNeeded];
[coordinator addCoordinatedAnimations:^{
[self.view layoutIfNeeded];
} completion:nil];
// The tabbar is going to appear
} else if (![prevFocusViewClassName isEqualToString:kUITabBarButtonClassName] &&
[nextFocusedView isEqualToString:kUITabBarButtonClassName]) {
[self.view layoutIfNeeded];
[coordinator addCoordinatedAnimations:^{
[self.view layoutIfNeeded];
} completion:nil];
}
}
我已修复了预期输出https://www.dropbox.com/s/c8jdw367a3bnb42/SampleMovingWithTabBar-2.zip?dl=0的代码