当 UIViewController 推送时显示 UITabBar
这是我的情况:
我在 UITabBarController
内有一个 UINavigationController
。当我向下钻取导航控制器时,在某些时候我必须隐藏 UITabBar
因为我希望视图拥有尽可能多的空间。
我通过在推送的 UIViewController 中使用 self.hidesBottomBarWhenPushed = YES 来实现这一点,并且效果很好。
但是,我想在以下推送的控制器中显示 UITabBar
。我尝试将 self.hidesBottomBarWhenPushed = NO 放入其他控制器中,但 UITabBar 不会回来。
正如文档所述,这似乎是正常的:
hidesBottomBarWhenPushed
如果是,则隐藏屏幕底部的栏;否则,不。如果是,底部栏将保持隐藏状态,直到视图控制器从堆栈中弹出。
事实上,当弹出此属性设置为 yes 的控制器时,选项卡栏确实会回来。
一旦隐藏了控制器,是否有任何正确的方法可以在按下控制器时显示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
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.
And indeed, when the controller with this property set to yes is popped, the tabbar does come back.
Is there any proper way to show the UITabBar
when a controller is pushed, once it's been hidden?
Thanks in advance
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
好吧,我们还有很长的路要走。
当您从文档中阅读时,默认行为很清楚:一旦视图控制器的
hides...
属性为 YES,标签栏就会隐藏,直到视图控制器弹出。你想要的直接与此相矛盾,出于各种原因,我首先建议不要采取这种方法。然而,这并不意味着它不可能实施。
hides...
属性设置回 NO您无法修改默认行为。要显示选项卡栏,堆栈中的所有视图控制器必须将其
hides...
属性设置为NO。因此,从隐藏选项卡栏的视图来看,如果您想在推送新视图时再次显示选项卡栏,则必须将之前的视图控制器的hides...
属性设置回不。
在推送新的视图控制器之前,将该属性设置回 NO。
通过这样做,您将再次拥有标签栏。但是,您会发现标签栏是从左侧推入的,而新视图是从右侧推入的。这显然是不可取的,所以我们需要解决这个问题。
事实是,当选项卡栏再次出现时使用的默认图层动作(动画)是从左侧推动过渡动画。 UITabBar 实现
- (id < CAAction >)actionForLayer:(CALayer *)layer forKey:(NSString *)key
方法,该方法告诉从左侧开始使用动画。我们需要重写此方法,以从右侧返回动画。为了重新显示选项卡栏,Cocoa 修改了其图层的
position
属性。因此,我们的新方法应该从右侧为键位置返回一个动画,对于所有其他键,它应该使用默认实现。请注意,Apple 没有记录标签栏使用position
的情况,因此在以下版本中可能会发生更改,恕不另行通知。无论如何,我们正在实现一些与苹果规范直接矛盾的东西,所以不能抱怨太多。但是,您不能仅使用子类化来重写该方法。因为即使您有 UITabBar 的自定义子类,您也无法修改 UITabBarController 类以使用它来代替默认的 UITabBar。
所以,事情变得有点复杂。为了将您自己的逻辑植入 UITabBar 类,您必须“交换”消息
actionForLayer: forKey:
的实现。首先,使用类别向 UITabBar 类添加一个新方法。
并在标签栏控制器的
viewDidAppear
方法中插入以下代码。您需要在
viewDidAppear
而不是viewDidLoad
中执行此操作,否则标签栏会在应用程序第一次显示时从右侧滑入。现在,当 UITabBar 实例收到消息
actionsForLayer forKey:
时,将调用自定义方法customActionForLayer forKey:
。它拦截关键位置
,并从右侧返回一个动画。如果它用于另一个键,它将调用消息的原始实现,该消息现在连接到消息defaultActionsForLayer forKey:
。好的,我们到了。请记住,当弹出视图时,您可能必须将 hides... 属性设置回 YES,因为在推送新视图时将其设置为 NO(并执行一些类似的技巧来正确设置动画) )。
我已经花了一些时间在这上面,但讽刺的是,我不得不说*不要再使用这个,因为它使用了 Cocoa 类的未记录信息(选项卡栏动画的“位置”键),矛盾已记录的行为,并且违反了 Apple 的人机界面指南。您可能会发现您的应用程序与以下 SDK 版本的工作方式不同,用户无法轻松采用该界面,甚至 Apple 在 App store 上拒绝您的应用程序。
那我的回答到底是为了什么?好吧,我想这是有关 iOS 开发的一些有趣主题的示例(并且证明我今天的效率非常低下:P)。
Okay, here have we an awfully long way to go.
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.
hides...
property back to NOYou 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'shides...
property back toNO
again.Just before you push a new view controller, set the property back to NO.
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.
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.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 keyposition
, and for all the other keys, it should use the default implementation. Note that usingposition
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.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.
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:
.First, add a new method to UITabBar class using category.
And in the
viewDidAppear
method of the tab bar controller, insert the following codes.You want to do this in
viewDidAppear
rather thanviewDidLoad
, because otherwise the tab bar will slide in from the right in the first time the application shows up.Now when a UITabBar instance gets a message
actionsForLayer forKey:
, the custom methodcustomActionForLayer forKey:
is invoked. It intercepts the keyposition
, 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 messagedefaultActionsForLayer forKey:
.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).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.
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).
以下是我在 iOS 5 中使用 Storyboard 时的方法:
在执行推送转场之前将
hidesBottomBarWhenPushed
属性设置为NO
:转场标识符显然由您来命名。
当视图控制器的视图消失时,立即将其设置回
YES
:使用
UITabBar
的所有正确动画,像魅力一样工作(在 iOS 5.1 上测试)。Here's my approach to this when using Storyboards in iOS 5:
Set the
hidesBottomBarWhenPushed
property toNO
before performing the push segue:The segue identifier is obviously up to you to name.
Set it back to
YES
immediately when the view controller's view will disappear:Works like a charm (tested on iOS 5.1) using all the right animations for the
UITabBar
.hidesBottomBarWhenPushed 并未弃用。
我发现使用以下方法实现隐藏和显示 UITabBar 非常简单:
因此,在推入DetailViewConroller 后,您应该将隐藏属性重置回NO。
这样,当详细信息视图弹出时,它将再次显示。
不需要对 viewWillApear/disapear 等进行任何额外的更改。
享受。
hidesBottomBarWhenPushed is not deprecated.
I found it is very simple to achieve the hide and show UITabBar using the following method:
So right after you push the detailViewConroller, you should reset the hide property back to NO.
This way it will show up again when the detail view pops back.
no need for any additional changes in viewWillApear/ disapear,etc..
Enjoy.