【问题标题】:how iphone facebook app make the navigation bar fixediphone facebook 应用程序如何修复导航栏
【发布时间】:2012-03-31 01:29:59
【问题描述】:

我是 iPhone 开发的新手,想询问有关导航控制器的问题。如何使导航控制器固定在整个应用程序上,例如 facebook 导航栏。它始终在导航栏中显示通知、好友和消息。

我正在尝试将自定义视图放在 titleView 中,但每次导航推送新视图时它都会消失?

【问题讨论】:

    标签: iphone facebook uinavigationcontroller xcode4.2


    【解决方案1】:

    你应该明白的是,显示的 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,您可能还需要创建一个委托或处理来自工具栏的通知,以捕获顶部视图控制器上的事件。

    这样,视图控制器的视图将使用导航控制器逻辑进行动画处理,但工具栏是窗口子视图,不会被导航操作自动更改。

    【讨论】:

    • 是的,这是正确的,我知道 :) 但现在我的问题是,如果是这种情况...... FACEBOOK 如何修复导航栏
    • 谢谢@A-Live,这似乎是一个很好的解决方案,但是当我尝试将任何视图添加到窗口并运行时,rootViewController 什么也没有出现......有没有像 Z -索引左右??
    • 是的,有。重要的是不要覆盖添加的视图:这就是为什么您需要首先将根视图添加到窗口,然后才需要自定义工具栏。结果将有两个子视图添加到窗口中,顶部有一个工具栏。仔细检查工具栏初始化,不要忘记设置它的框架。
    【解决方案2】:

    这对我有用:

    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];
    

    【讨论】:

      【解决方案3】:

      这里发布了一个类似的问题(https://stackoverflow.com/questions/16773312/facebook-like-navigationbar),不幸的是它很快就关闭了。我在这里赎回了它应有的荣耀。

      如果您将导航视为基于选项卡的应用程序(带有隐藏选项卡),则可以轻松实现持久导航栏。

      使用故事板:

      1. 创建一个新的 UINavigationController (Nav 1)。
      2. 将 UITabController 设置为 Nav 1 的根视图控制器。(Tab Bar)请注意,它将拥有自己的导航栏(我已将其标记为“Persistent Nav Bar”)。
      3. 创建另一个 UINavigationController (Nav 2)。
      4. 将您选择的视图控制器(我的视图控制器)设置为导航 2 的根视图控制器。
      5. 将 Nav 2 设置为 Tab Bar 控制器的第一个(标签)视图控制器。

      6. 对于导航 1:在属性检查器 -> 导航控制器 -> 栏可见性下,确保该框已勾选(以便显示导航栏)。

      7. 对于导航 2:在属性检查器下 -> 导航控制器 -> 栏可见性,确保该框未勾选(以便 不会显示其导航栏)。

      如果您运行应用程序,您应该会看到标签栏的标题可见,而视图控制器的标题则隐藏。这为您提供了持久导航栏的基础知识。您可以从 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 循环和一点创意,您可以在导航栏中重新创建自定义按钮(基于选项卡),它们执行与选项卡栏相同的功能。这样可以节省屏幕空间(因为标签栏非常大)并且仍然使用标签栏来执行视图交换。

      【讨论】:

      • 但是侧视图控制器呢?例如,我想为此目的使用 IIViewDeckController,deckController 不应该作为根控制器吗?整个解释做得很好。我设法通过继承 navigationController 并将工具栏添加到导航控制器视图中来做到这一点,并在推送新控制器时将其置于前面。
      猜你喜欢
      • 2015-06-24
      • 1970-01-01
      • 2013-10-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-15
      相关资源
      最近更新 更多