32

我有一个带有UITableView菜单的 iPhone 应用程序。选择表中的一行时,将适当的视图控制器推到应用程序的UINavigationController堆栈上。

我的问题是MenuViewController不需要工具栏,但是UIViewControllers被推到堆栈上的工具栏需要。每个UIViewController被推入的电话setToolbarHidden:animated:viewDidAppear:为了隐藏工具栏,我调用setToolbarHidden:animated:viewWillDisappear:.

显示工具栏有效,这样当推送的视图出现时,工具栏向上滑动并且视图正确调整大小。但是,当按下后退按钮时,工具栏会向下滑动,但视图不会调整大小。这意味着当另一个视图过渡时,视图底部有一条黑色条带。我尝试在隐藏工具栏之前将工具栏的高度添加到视图的高度,但这会导致视图在过渡,以便仍然有一个黑条。

我意识到我可以管理自己的 UIToolbar,但为了方便起见,我想使用UINavigationControllers内置的 UIToolbar。

这个论坛帖子提到了同样的问题,但没有提到解决方法。

4

11 回答 11

24

我也遇到过这个问题。就我而言,我发现成功隐藏工具栏而不显示窗口背景的唯一方法是调用[self.navigationController setToolbarHidden:YES animated:animated]视图控制器的-viewDidAppear:方法。

于 2010-04-30T18:39:16.283 回答
6

对于推送时不需要工具栏的 UIViewController,您可以考虑使用

为 UIViewController 实现 hidesBottomBarWhenPushed 方法:

// method to be added to the UIViewController that has no toolbar
- (BOOL) hidesBottomBarWhenPushed {
    return YES;
}

或者在推入 UIViewController 之前,设置 hidesBottomBarWhenPushed 的值:

viewControllerWithNoToolBar.hidesBottomBarWhenPushed = YES
[self.navigationController pushViewController:viewControllerWithNoToolBar animated:YES];
于 2013-02-10T09:58:11.583 回答
6

我对这个问题的答案不满意,所以我发布了自己的:同时引用源视图控制器和目标视图控制器

我得到的答案解决了我的问题。它也可能对您有用(尽管这个问题已经很老了,但我认为这可能会帮助像我这样阅读这篇文章六次寻找提示的人)。

这就是我所做的。我不知道标记协议是否是惯用的objective-c,但我将它们比作我在c#中使用的属性,所以我有这个标记协议:

@protocol HidesNavigationItem
@end

我将 UINavigationControllerDelegate 添加到我的 AppDelegate。我还不确定这是否是一件好事。我曾考虑将该实现保存在另一个对象中,但现在,我把它放在这里。这是实现:

#pragma mark Navigation Controller Delegate
-(void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    [navigationController setNavigationBarHidden:[viewController conformsToProtocol:@protocol(HidesNavigationItem)] animated:animated];
}

这样,我可以像这样在 UIViewController 实现上设置我的标记协议:

@interface MyViewController : UIViewController <HidesNavigationItem>

如果我没有那个接口,它会把它放回去。

最后,在我的 appDelegate 的 application:didFinishLaunchingWithOptions: 方法中,我像这样连接代理:

if ([self.window.rootViewController isMemberOfClass:[UINavigationController class]])
    ((UINavigationController*)self.window.rootViewController).delegate = self;

现在我没有黑匣子,也没有柴郡猫。我的解决方案当然是关于导航栏,但我确信它对工具栏同样适用。这与 Danra 的回答非常相似,只是我得到了没有“动画:动画”的黑匣子。

于 2012-01-24T20:23:35.863 回答
1

这里的问题是UITableView' 的框架被设置为不与UIToolbar. 也就是说,它位于UIToolbar. 当您将 next 推UIViewControllerUINavigationController堆栈中时,同时删除,除了它后面UIToolbar没有任何东西可以显示,除非您在它的位置放了一些东西UIWindow

过渡后没有尴尬动画的一种解决方法是将您UITableView放在一个UIView“容器”中,该“容器”与您的常规视图共享相同的帧,但UIToolbar与您希望在过渡期间看到的所需颜色(例如白色)重叠。

要制定下重叠,您可以将您的设置UIViewControllerwantsFullScreenLayout = YES. 然后,您将确保您UITableView的框架与使用容器之前的框架相同。即它位于导航栏下方和工具栏上方。

这可以通过编写一个自定义UIViewController并使用它而不是 .来变得更加优雅UITableViewController,或者通过偷偷摸摸UIViewUITableView在现有的UITableViewController.

于 2012-01-18T17:10:51.893 回答
1

要在新视图控制器中显示工具栏,只需添加以下内容:

- (void)viewWillAppear:(BOOL)animated
{
    [self.navigationController setToolbarHidden:NO animated:animated];
    [super viewWillAppear:animated];
}

隐藏工具栏:

- (void)viewWillAppear:(BOOL)animated
{
    [self.navigationController setToolbarHidden:YES animated:animated];
    [super viewWillAppear:animated];
}

在屏幕之间移动时,使用以下代码推送新的视图控制器:

SettingsRecordingViewController *vc = [[SettingsRecordingViewController alloc] initWithNibName:@"SettingsRecordingViewController" bundle:[NSBundle mainBundle]]; 
[self.navigationController pushViewController:vc animated:YES];      
[vc release];

如果它具有不同的工具栏状态(隐藏/显示),则将显示隐藏/显示工具栏的漂亮动画。

于 2011-04-13T19:43:35.017 回答
1

尝试实现 UINavigationControllerDelegate 并将其设置为导航控制器的委托属性。这对我来说实现了您在帖子中描述的内容,没有可见的伪影。

下面的代码假设 secondController 通过在 firstController 中执行的操作被推送到导航视图中。

MyNavigationControllerDelegate.h

@interface MyNavigationControllerDelegate : NSObject<UINavigationControllerDelegate> {
}

-(void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated;
-(void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated;

@end

MyNavigationControllerDelegate.m

#import "MyNavigationControllerDelegate.h"
#import "AppDelegate_Shared.h"

@implementation MyNavigationControllerDelegate

-(void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
    if ([AppDelegate_Shared sharedDelegate].firstController  == viewController ) {
        [navigationController setNavigationBarHidden:TRUE];
        [navigationController setToolbarHidden:FALSE];
    }
}

-(void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
    if ([AppDelegate_Shared sharedDelegate].secondController == viewController ) {
        [navigationController setNavigationBarHidden:FALSE];
        [navigationController setToolbarHidden:TRUE];
    }
}

@end

sharedDelegate 只是一个辅助方法:

AppDelegate_Shared.m

+ (AppDelegate_Shared*)sharedDelegate {
    return (AppDelegate_Shared*)[[UIApplication sharedApplication] delegate];
}
于 2010-10-13T07:48:10.613 回答
0

我同意杰夫的回答。但是,如果我在 viewController 的 -viewDidAppear 方法中隐藏工具栏,通过该方法推送不同的 viewController,则会出现 UI 故障。

为了避免这种情况,我进行了试验,发现在 -viewWillAppear 调用中调用 -setToolbarHidden 确实隐藏了工具栏,但正如问题所述,虽然展开的视图不会被 tableview 行占用。

为了解决这个问题,我已更改为以下代码,现在它可以正常工作了:

- (void)viewDidLoad
{
    [super viewDidLoad];
.
.
.
    [self reframeRowHeight];
    [self.menuItemTableView addObserver:self
                             forKeyPath:@"frame"
                                options:NSKeyValueObservingOptionNew
                                context:nil];
    [self.menuItemTableView setBounces:NO];
.
.
.
}
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if ([keyPath isEqualToString:@"frame"])
    {
        [self reframeRowHeight];
    }
}

-(void)reframeRowHeight
{

    [self.menuItemTableView setRowHeight:self.menuItemTableView.frame.size.height/self.menuItems.count];
    [self.menuItemTableView reloadData];
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
.
.
.
    // Bad Apple! - http://stackoverflow.com/questions/2339721/hiding-a-uinavigationcontrollers-uitoolbar-during-viewwilldisappear
    [self.navigationController setToolbarHidden:YES animated:YES];
.
.
.
}
于 2013-02-25T09:05:19.237 回答
0

我使用自定义背景图像作为工具栏背景,使用自定义图像作为表格背景。当视图从另一个表视图来回转换时,我在底部的黑条上遇到了同样的问题。但是我设置

self.navigationController.toolbar.barStyle = UIBarStyleBlackTranslucent;

在 viewDidLoad 中。

这会将背景图像设置为背景的全部潜在大小,如果您有一个透明的工具栏,这将是有意义的。当您使用标准的不透明工具栏时,这可能不是一个好的解决方法,但对于那些自定义工具栏的人来说,您可以两全其美。

于 2012-06-30T01:20:52.747 回答
0

管理工具栏状态(即哪个 VC 需要/不需要工具栏)很快就会变得棘手。

我已经成功地遵循了这条规则:

对于每个视图控制器,在 中viewWillAppear(),决定它是否需要工具栏,然后navigationController?.setToolbarHidden(true or false, animated: animated)分别调用。

这样,每个视图控制器都以正确的工具栏状态开始,您不必担心在视图控制器关闭时“恢复”工具栏状态。

于 2015-07-01T06:08:21.860 回答
-2

这只是在黑暗中的一次野刺,但也许你应该在隐藏工具栏后让 runloop 运行一次:

[viewController setToolbarHidden:YES animated:YES];
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.0]];
于 2010-02-26T07:36:01.167 回答
-3

我遇到了同样的问题,这是对我有用的解决方案。假设您正在推动SomeUIViewController您的导航堆栈。

在以下接口中定义此(私有)ivar SomeUIViewController

// keep a reference to the navigation controller for use in viewDidDisappear:(BOOL)animated method
UINavigationController * _navigationController; 

实现以下方法SomeUIViewController

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    // here, your controller still has a reference to self.navigationController
    _navigationController = [self.navigationController retain];
}

- (void)viewDidDisappear:(BOOL)animated {
    // at this point, self.navigationController = 0x0, so
    // use your retained reference to the navigation controller to perform any last minute operations, then release

    [_navigationController setToolbarHidden:YES];
    [_navigationController release];

    [super viewDidDisappear:animated];
}

这个想法是你想在' 的视图消失后隐藏导航控制器拥有的工具栏。 SomeUIViewController这样,您可以避免任何不需要的显示伪影。

免责声明

这只是一个答案,显示了针对所述问题的解决方法。它只是为了指出框架内部工作的细节。它也可以作为不提交到 Apple AppStore的示例。

于 2010-05-26T14:28:37.707 回答