我正试图将视图捕捉到UITabBarController的tabBar(UITabBar),以使其永远不会隐藏(就像苹果在tvOS应用商店的"特色"选项卡中所做的那样)。
我可以通过在直接包含在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
这是一个bug还是预期的行为?
我正试图在另一个更复杂的应用程序中实现这种"视图不隐藏在选项卡栏下"的行为,但我得到了同样奇怪的行为。尽管在本例中没有涉及UINavigationController。视图直接位于UIViewController中(UIViewController是UITabBarController的viewControllers数组的一部分)。
什么可以阻止在动画过程中遵守"自动布局"约束?
在我链接到的演示项目中,我的视图控制器层次结构是这样的(UINavigationController中的视图控制器是在显示/隐藏选项卡栏时不动画的):
<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的属性(类似于constant
)用于动画,则自动布局在瞬态动画过程中会遵守约束。
核心动画API包括UIView的基于块的动画。如果你有兴趣进一步阅读,那么这里是wwdc视频
但是,看看你的代码,我不认为这是你的问题。您希望在UITabbar
设置动画时遵守布局约束。您只需要在viewDidLayoutSubviews
而不是videDidAppear
中设置约束,就应该完全使用现有代码进行设置。
编辑---
我得到了关于这个问题的更多细节。所以,首先,它不是苹果公司的一个bug。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