当UIViewController推送时显示UITabBar [英] Show UITabBar when UIViewController pushed

查看:135
本文介绍了当UIViewController推送时显示UITabBar的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我的情况:

我在 UITabBarController 中有一个 UINavigationController 。当我向下钻取导航控制器时,我必须隐藏 UITabBar ,因为我希望视图尽可能多的空间。

我通过在推送的 UIViewController 中使用 self.hidesBottomBarWhenPushed = YES 来做到这一点,并且它运行良好。

但是,我想在以下推送的控制器中显示 UITabBar 。我试图在其他控制器中放入 self.hidesBottomBarWhenPushed = NO ,但是UITabBar不会回来。

Here's my situation :
I have a UINavigationController inside a UITabBarController. When I drill down the navigation controller, at some point I have to hide the UITabBar because I want the view to have as much space as possible.
I do that by using self.hidesBottomBarWhenPushed = YES inside the pushed UIViewController, and it works quite well.
However, I want to show the UITabBar back in the following pushed controllers. I've tried to put self.hidesBottomBarWhenPushed = NO in the other controllers, but the UITabBar won't come back.

文档说明似乎是正常的:

It seems to be normal as the documentation states :

hidesBottomBarWhenPushed

如果是,则隐藏屏幕底部的栏;否则,不。如果是,则底部栏保持隐藏,直到视图控制器从堆栈弹出。

实际上,当具有此属性的控制器设置时如果弹出,则标签栏会回来。

And indeed, when the controller with this property set to yes is popped, the tabbar does come back.

是否有任何正确的方法来显示 UITabBar 当控制器被按下时,一旦它被隐藏了?

Is there any proper way to show the UITabBar when a controller is pushed, once it's been hidden?

提前致谢

推荐答案

好的,这里有一个非常漫长的路要走。

Okay, here have we an awfully long way to go.

当您从文档中读取时,默认行为是明确的:一次视图控制器的隐藏... 属性为YES,标签栏将隐藏,直到弹出视图控制器。您想要的与此直接相矛盾,并且出于各种原因,我首先建议不要采用这种方法。

As you read from the document, the default behavior is clear: once a view controller's hides... property is YES, the tab bar is hidden until the view controller is popped. What you want directly contradicts this, and for various reasons, I would first recommend not to take this approach.

但是,这并不意味着无法实现。

However, it doesn't mean it is impossible to implement.


  • 设置隐藏...... 属性返回NO

  • Setting hides... property back to NO

您无法修改默认行为。要显示标签栏,堆栈中的所有视图控制器必须将其隐藏... 属性设置为NO。因此,从隐藏标签栏的视图中,如果要在按下新视图时再次显示该栏,则必须设置上一个视图控制器的隐藏... 属性再次返回

You cannot modify the default behavior. To show the tab bar, all view controllers in the stack must set their hides... property to NO. So from the view where the tab bar is hidden, if you want to show the bar again when a new view is pushed, you have to set the previous view controller's hides... property back to NO again.

在你推新视图控制器之前,将属性设置回NO。

Just before you push a new view controller, set the property back to NO.

// ... prepare viewControllerToPush

self.hidesBottomBarWhenPushed = NO;
[self.navigationController pushViewController:viewControllerToPush animated:YES];
[viewControllerToPush release];

通过执行此操作,您将再次拥有标签栏。但是,您将识别从左侧推入标签栏,而从右侧推入新视图。这显然是不可取的,所以我们需要解决这个问题。

By doing this, you will have the tab bar again. However, you will recognize the tab bar is pushed in from the left, while the new view is pushed from the right. This is clearly not desirable, so we need to fix this.


  • 覆盖图层动作对于标签栏

事实上,标签栏再次出现时使用的默认图层动作(动画)是推送从左侧过渡动画。 UITabBar实现 - (id< CAAction>)actionForLayer:(CALayer *)图层forKey:(NSString *)key 告诉我使用左边动画的方法案件。我们需要覆盖此方法,以便从右侧返回动画。

The thing is, the default layer action (the animation) used when the tab bar appears again, is a push transition animation from the left. UITabBar implements - (id < CAAction >)actionForLayer:(CALayer *)layer forKey:(NSString *)key method that tells to use the animation from the left for the case. We need to override this method, to return an animation from the right instead.

要显示标签栏,Cocoa会修改其图层的位置 property。因此,我们的新方法应该从右侧为键位置返回一个动画,对于所有其他键,它应该使用默认实现。请注意,Apple未记录使用标签栏的位置,因此在以下版本中如有更改,恕不另行通知。我们正在实现一些与Apple规范直接相悖的东西,所以不能抱怨太多。

To show the tab bar back, Cocoa modifies its layer's position property. Therefore, our new method should return an animation from the right for the key position, and for all the other keys, it should use the default implementation. Note that using position for the tab bar is not documented by Apple, so it's subject to change without a notice in the following versions. We are implementing something directly contradicts Apple's specification anyway, so can't complain much.

但是,你不能只使用子类来覆盖方法。因为即使你有一个UITabBar的自定义子类,你也不能修改UITabBarController类来使用它而不是默认的UITabBar。

However, you cannot just use subclassing to override the method. Because even if you have a custom subclass of UITabBar, you cannot modify UITabBarController class to use it instead of the default UITabBar.

所以,它会变得有点复杂。为了将自己的逻辑植入UITabBar类,你必须'交换'消息的实现 actionForLayer:forKey:

So, it gets a bit more complex. In order to implant your own logic to UITabBar class, you have to 'swap' the implementation for the message actionForLayer: forKey:.

首先,使用类别向UITabBar类添加一个新方法。

First, add a new method to UITabBar class using category.

@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 标签栏控制器的方法,插入以下代码。

And in the viewDidAppear method of the tab bar controller, insert the following codes.

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 ,因为否则标签栏会在应用程序第一次显示时从右侧滑入。

You want to do this in viewDidAppear rather than viewDidLoad, because otherwise the tab bar will slide in from the right in the first time the application shows up.

现在,当UITabBar实例收到消息 actionsForLayer forKey:时,将调用自定义方法 customActionForLayer forKey:。它拦截键位置,并从右侧返回一个动画。如果它是另一个键,它会调用消息的原始实现,现在它连接到消息 defaultActionsForLayer forKey:

Now when a UITabBar instance gets a message actionsForLayer forKey:, the custom method customActionForLayer forKey: is invoked. It intercepts the key position, and returns an animation from the right. If it's for another key, it invokes the original implementation of the message, which is now connected to the message defaultActionsForLayer forKey:.

好的,我们有。请记住,当弹出视图时,您可能必须将隐藏... 属性设置回YES,因为在推送新视图时将其设置为NO(并执行一些操作)类似的技巧,以适当的动画)。

Okay, there we are. Remember when popping back the views, you may have to set the hides... property back to YES, because you set it to NO when pushing a new view (and do some similar tricks to animate it properly).

我花了一些时间在这上面但具有讽刺意味的是,我不得不再说 *不要再使用,因为它使用的是未记录的信息Cocoa类(标签栏动画的位置键)与记录的行为相矛盾,并且违反了Apple的人机界面指南。您可能会发现您的应用程序与以下SDK版本不同,用户无法轻松采用该界面,甚至Apple拒绝您在App Store上的应用程序。

I've spent some time on this but ironically, I have to say *Do not use this again, because it uses an undocumented information of Cocoa classes ("position" key for tab bar animation), contradicts the documented behaviors, and is against Apple's human interface guideline. You may find out that your application wouldn't work the same with the following SDK versions, that the users cannot easily adopt the interface, or even that Apple rejects your application on App store.

那我的答案到底是什么?好吧,我猜想一个关于iOS开发的一些有趣主题的例子(以及证明我今天非常无效的证据:P)。

Then what on earth is my answer for? Well, an example of some interesting topics on the iOS development, I guess (and a proof showing that I'm terribly unproductive today :P).

这篇关于当UIViewController推送时显示UITabBar的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆