【发布时间】:2012-03-31 01:29:59
【问题描述】:
我是 iPhone 开发的新手,想询问有关导航控制器的问题。如何使导航控制器固定在整个应用程序上,例如 facebook 导航栏。它始终在导航栏中显示通知、好友和消息。
我正在尝试将自定义视图放在 titleView 中,但每次导航推送新视图时它都会消失?
【问题讨论】:
标签: iphone facebook uinavigationcontroller xcode4.2
我是 iPhone 开发的新手,想询问有关导航控制器的问题。如何使导航控制器固定在整个应用程序上,例如 facebook 导航栏。它始终在导航栏中显示通知、好友和消息。
我正在尝试将自定义视图放在 titleView 中,但每次导航推送新视图时它都会消失?
【问题讨论】:
标签: iphone facebook uinavigationcontroller xcode4.2
你应该明白的是,显示的 UINavigationBar 是位于导航控制器层次结构顶部的视图控制器的一个属性。如您所见,您可以尝试自定义每个视图控制器的 UINavigationBar 的 titleView,例如在视图将出现。您可以使用
访问导航栏self.navigationController.navigationBar
其中 self 是加载的视图控制器引用。
如果您希望在屏幕上的某处有一个持久视图,其中一种解决方案如下:在 app-delegate 类中声明一个属性,将视图直接添加到根视图之后的窗口中,如下所示:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// something here ...
// root view controller
[window addSubview:myRootViewController.view];
// toolbar
MyToolbar * tb = [MyToolbar new];
tb.barStyle = UIBarStyleDefault;
[tb sizeToFit];
tb.frame = CGRectMake(0, 0, 320, 70);
[window addSubview:tb];
self.globalToolBar = tb;
[tb release];
然后您可以通过这种方式从任何视图更新工具栏(在这种情况下,它通常可以是任何视图):
[[[[UIApplication sharedApplication] delegate] globalToolBar] updateRightButtonItem]
因此,您需要使用 MyToolbar 子类化 UIToolBar,在那里添加一些 UI 方法,例如 updateRightButtonItem,您可能还需要创建一个委托或处理来自工具栏的通知,以捕获顶部视图控制器上的事件。
这样,视图控制器的视图将使用导航控制器逻辑进行动画处理,但工具栏是窗口子视图,不会被导航操作自动更改。
【讨论】:
这对我有用:
toolBar = [[UIView alloc]initWithFrame:CGRectMake(105, 20, 105, 44)];
notificationsBtn = [UIButton buttonWithType:UIButtonTypeCustom];
messagesBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[notificationsBtn setImage:[UIImage imageNamed:@"notifications-icon.png"] forState:UIControlStateNormal];
[notificationsBtn setFrame:CGRectMake(35, 0, 35 , 44)];
[notificationsBtn addTarget:self action:@selector(showNotifications:) forControlEvents:UIControlEventTouchUpInside];
[messagesBtn setImage:[UIImage imageNamed:@"messages-icon.png"] forState:UIControlStateNormal];
[messagesBtn setFrame:CGRectMake(70, 0, 35 , 44)];
[messagesBtn addTarget:self action:@selector(showMessages:) forControlEvents:UIControlEventTouchUpInside];
[toolBar addSubview:notificationsBtn];
[toolBar addSubview:messagesBtn];
[_window.rootViewController.view addSubview:toolBar];
【讨论】:
这里发布了一个类似的问题(https://stackoverflow.com/questions/16773312/facebook-like-navigationbar),不幸的是它很快就关闭了。我在这里赎回了它应有的荣耀。
如果您将导航视为基于选项卡的应用程序(带有隐藏选项卡),则可以轻松实现持久导航栏。
使用故事板:
将 Nav 2 设置为 Tab Bar 控制器的第一个(标签)视图控制器。
对于导航 1:在属性检查器 -> 导航控制器 -> 栏可见性下,确保该框已勾选(以便显示导航栏)。
如果您运行应用程序,您应该会看到标签栏的标题可见,而视图控制器的标题则隐藏。这为您提供了持久导航栏的基础知识。您可以从 My View Controller 继续将视图推送到堆栈上,并且它将保持持久性。呈现一个 MODAL 视图会带来一个新的上下文,所以持久性会丢失。如果您重复这些步骤,您应该也可以为模态呈现的视图创建相同的效果。
此答案的其余部分涉及隐藏标签栏和管理导航栏元素。
这很好,但是如何将自定义视图放置在导航栏中,以及如何隐藏该标签栏?
创建 UITabBarController 的子类,并将其分配给故事板中的 Tab Bar 控制器。
隐藏标签栏
您可以通过各种方式隐藏标签栏。如果你有兴趣,这里有更多关于那个 (How to hide uitabbarcontroller);这个小 sn-p 改编自我在该线程中的回答:
CGRect screenRect = [[UIScreen mainScreen] bounds];
float fHeight = screenRect.size.height;
if( UIDeviceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation) )
{
fHeight = screenRect.size.width;
}
for(UIView *view in self.view.subviews){
if([view isKindOfClass:[UITabBar class]]){
[view setFrame:CGRectMake(view.frame.origin.x, fHeight, view.frame.size.width, view.frame.size.height)];
}else{
[view setFrame:CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width, fHeight)];
}
}
这会将标签栏移出视图并调整视图大小以填充空间(没有动画,就好像它从未存在过一样)。将此 sn-p 添加到 viewDidLoad 的开头以消除该栏。
导航栏中的自定义视图
在我们的 TB 子类的 viewDidLoad 方法中,您可以使用按钮创建自定义视图并将其添加到导航栏,如下所示:[self.navigationItem setTitleView:myCustomTitleView]; Easy。
如果它没有正确显示,请确保在将其设置为 titleView 之前定义它的框架。然后在添加之后,使用[myCustomTitleView sizeToFit] 让它紧贴在导航栏中。
设置栏按钮项
设置左右栏按钮项目需要对符号进行小的更改。通常,您将通过引用self.navigationItem.leftBarButtonItem 来设置左侧栏按钮。这个引用实际上是指向 HIDDEN 导航栏的左栏按钮。要访问 VISIBLE 导航栏,请使用 self.tabBarController.navigationItem.leftBarButtonItem。简单!
处理丢失的 bar back 按钮项
使用持久导航栏牺牲的一件事是推送视图的管理。后退箭头之类的东西不会显示(它们出现在隐藏的导航栏上)。您可以通过将 TabBarController 子类设置为其视图控制器(应该都是 UINavigationControllers)的委托来克服这个问题。
for (UINavigationController *navController in self.viewControllers) {
navController.delegate = self;
}
每当这些 UINavigationController 中的任何一个推送另一个视图时,您都可以使用此委托方法拦截此操作:
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated;
在这里,您可以查看推送了多少视图控制器:
if(navigationController.viewControllers.count > 1){
//create a custom back button here and add it to the nav bar
}else{
//set the left bar button (where the custom back button would sit) to nil
}
自定义后退按钮可以调用标签栏控制器子类中的方法,该方法告诉当前选定的视图控制器弹出其当前视图。
这是 Facebook 的做法吗?
我无法验证这是否是 Facebook 的做法(可能不是),但它会达到类似的效果。我在我最新的应用程序 (http://www.waterboyapp.com) 中有效地使用了它,Apple 很高兴地接受了它。我希望有人以前在网上发布过此内容,因此我在这里的贡献是为了节省数小时/数天的搜索时间。
一边
这个实现的额外好处(除了简单和优雅)是您可以将多个视图控制器链接到选项卡栏。通过 for 循环和一点创意,您可以在导航栏中重新创建自定义按钮(基于选项卡),它们执行与选项卡栏相同的功能。这样可以节省屏幕空间(因为标签栏非常大)并且仍然使用标签栏来执行视图交换。
【讨论】: