这是我的情况:
我在UINavigationController
内有一个UITabBarController
。当我向下钻取导航控制器时,我必须隐藏UITabBar
,因为我希望视图具有尽可能多的空间。
我是通过在推送的self.hidesBottomBarWhenPushed = YES
内使用UIViewController
来做到的,而且效果很好
但是,我想在以下推送的控制器中显示UITabBar
。我试图将self.hidesBottomBarWhenPushed = NO
放在其他控制器中,但是UITabBar不会回来。
文件说明似乎是正常的:
hidesBottomBarWhenPushed
If YES, the bar at the bottom of the screen is hidden; otherwise, NO. If YES, the bottom bar remains hidden until the view controller is popped from the stack.
事实上,当弹出具有此属性设置为yes的控制器时,标签栏会回来。
一旦隐藏了控制器,有没有正确的方法显示UITabBar
?
提前致谢
答案 0 :(得分:13)
hidesBottomBarWhenPushed不被弃用。 我发现使用以下方法实现隐藏并显示UITabBar非常简单:
self.hidesBottomBarWhenPushed = YES;
[self.navigationController pushViewController:detailViewController animated:YES];
[detailViewController release];
self.hidesBottomBarWhenPushed = NO;
因此,在推送detailViewConroller之后,您应该将hide属性重置为NO。 这样,当细节视图弹出时,它将再次出现。 在viewWillApear / disapear等中无需任何其他更改。 请享用。
答案 1 :(得分:6)
好的,我们还有很长的路要走。
当您从文档中读取时,默认行为是明确的:一旦视图控制器的hides...
属性为YES,标签栏将被隐藏,直到弹出视图控制器。你想要的东西与此直接相矛盾,并且出于各种原因,我首先建议不要采用这种方法。
但是,这并不意味着无法实施。
hides...
属性设置为NO 您无法修改默认行为。要显示选项卡栏,堆栈中的所有视图控制器必须将其hides...
属性设置为NO。因此,从隐藏标签栏的视图中,如果要在按下新视图时再次显示该栏,则必须再次将先前视图控制器的hides...
属性设置回NO
。
在推送新视图控制器之前,将属性设置回NO。
// ... prepare viewControllerToPush
self.hidesBottomBarWhenPushed = NO;
[self.navigationController pushViewController:viewControllerToPush animated:YES];
[viewControllerToPush release];
通过这样做,您将再次拥有标签栏。但是,您将识别从左侧推入标签栏,而从右侧推入新视图。这显然是不可取的,所以我们需要解决这个问题。
问题是,标签栏再次出现时使用的默认图层动作(动画)是左侧的推送过渡动画。 UITabBar实现了- (id < CAAction >)actionForLayer:(CALayer *)layer forKey:(NSString *)key
方法,该方法告诉我使用左边的动画来表示案例。我们需要覆盖此方法,而是从右侧返回动画。
要显示标签栏,Cocoa会修改其图层的position
属性。因此,我们的新方法应该从右侧为键position
返回一个动画,对于所有其他键,它应该使用默认实现。请注意,Apple未记录使用position
标签栏,因此在以下版本中如有更改,恕不另行通知。无论如何,我们正在实施一些与苹果规范直接相悖的东西,所以不能抱怨太多。
但是,您不能只使用子类来覆盖该方法。因为即使您有UITabBar的自定义子类,也无法修改UITabBarController类以使用它而不是默认的UITabBar。
所以,它变得有点复杂。为了将自己的逻辑植入UITabBar类,您必须“交换”消息actionForLayer: forKey:
的实现。
首先,使用category为.UITabBar类添加一个新方法。
@interface UITabBar(customAction)
@end
@implementation UITabBar(customAction)
- (id < CAAction >)customActionForLayer:(CALayer *)layer forKey:(NSString *)key {
if ([key isEqualToString:@"position"]) {
CATransition *pushFromRight = [[CATransition alloc] init];
pushFromRight.duration = 0.25;
pushFromRight.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
pushFromRight.type = kCATransitionPush;
pushFromRight.subtype = kCATransitionFromRight;
return [pushFromRight autorelease];
}
return [self defaultActionForLayer:layer forKey:key];
}
@end
在标签栏控制器的viewDidAppear
方法中,插入以下代码。
Method original = class_getInstanceMethod([UITabBar class], @selector(actionForLayer:forKey:));
Method custom = class_getInstanceMethod([UITabBar class], @selector(customActionForLayer:forKey:));
class_replaceMethod([UITabBar class], @selector(actionForLayer:forKey:), method_getImplementation(custom), method_getTypeEncoding(custom));
class_addMethod([UITabBar class], @selector(defaultActionForLayer:forKey:), method_getImplementation(original), method_getTypeEncoding(original));
您希望在viewDidAppear
而非viewDidLoad
中执行此操作,否则标签栏将在应用程序首次显示时从右侧滑入。
现在,当UITabBar实例收到消息actionsForLayer forKey:
时,将调用自定义方法customActionForLayer forKey:
。它拦截键position
,并从右侧返回一个动画。如果它是另一个密钥,它会调用消息的原始实现,该消息现在已连接到消息defaultActionsForLayer forKey:
。
好的,我们有。请记住,在弹出视图时,您可能必须将hides...
属性设置回YES,因为在推送新视图时将其设置为NO(并执行一些类似的技巧来正确设置动画)。
我花了一些时间在这上面但具有讽刺意味的是,我不得不再说 *不要再使用,因为它使用了Cocoa类的未记录信息(标签栏动画的“position”键) ),与记录的行为相矛盾,并且违反了Apple的人机界面指南。您可能会发现您的应用程序与以下SDK版本不同,用户无法轻松采用该界面,甚至Apple拒绝您在App Store上的应用程序。
那我的答案到底是什么?好吧,我猜想一个关于iOS开发的一些有趣主题的例子(以及证明我今天非常无效的证据:P)。
答案 2 :(得分:4)
这是我在iOS 5中使用Storyboard时的方法:
在执行push segue之前将hidesBottomBarWhenPushed
属性设置为NO
:
- (void)prepareForSegue:(UIStoryboardSegue*)segue sender:(id)sender
{
if( [segue.identifier isEqualToString:@"PushDetailView"] )
{
self.hidesBottomBarWhenPushed = NO;
}
[super prepareForSegue:segue sender:sender];
}
segue标识符显然取决于你的名字。
当视图控制器的视图消失时立即将其设置回YES
:
- (void)viewWillDisappear:(BOOL)animated
{
self.hidesBottomBarWhenPushed = YES;
[super viewWillDisappear:animated];
}
使用UITabBar
的所有正确动画,像魅力(在iOS 5.1上测试)一样工作。