【问题标题】:Prevent a UISearchDisplayController from hiding the navigation bar防止 UISearchDisplayController 隐藏导航栏
【发布时间】:2011-02-18 06:41:50
【问题描述】:

每当用户开始编辑UISearchDisplayController 的搜索栏时,搜索控制器就会激活并隐藏视图的导航栏,同时显示搜索表视图。是否可以防止 UISearchDisplayController 在不重新实现的情况下隐藏导航栏?

【问题讨论】:

    标签: iphone iphone-sdk-3.0 uinavigationcontroller uisearchdisplaycontroller


    【解决方案1】:

    从 iOS 8.0 开始,可以通过将 UISearchControllerself.searchController.hidesNavigationBarDuringPresentation 属性设置为 false 来实现相同的行为。

    Swift 中的代码如下所示:

    searchController.hidesNavigationBarDuringPresentation = false
    

    【讨论】:

    • 此 API 从 iOS 8.0 开始可用
    • 是的,它从 iOS 8.0 开始可用。
    【解决方案2】:

    我刚刚调试了一下 UISearchDisplayController ,发现它正在调用 UINavigationController 上的私有方法来隐藏导航栏。这发生在 -setActive:animated: 中。如果你继承 UISearchDisplayController 并用下面的代码覆盖这个方法,你可以通过假装它已经隐藏来防止导航栏被隐藏。

    - (void)setActive:(BOOL)visible animated:(BOOL)animated;
    {
        if(self.active == visible) return;
        [self.searchContentsController.navigationController setNavigationBarHidden:YES animated:NO];
        [super setActive:visible animated:animated];
        [self.searchContentsController.navigationController setNavigationBarHidden:NO animated:NO];
        if (visible) {
            [self.searchBar becomeFirstResponder];
        } else {
            [self.searchBar resignFirstResponder];
        }   
    }
    

    让我知道这是否适合您。我也希望这不会在未来的 iOS 版本中中断...仅在 iOS 4.0 上测试。

    【讨论】:

    • 你是怎么解决这个问题的?我想更改搜索的行为,以便在用户单击搜索按钮之前保持表格视图变暗,并且您的调试解决方案似乎是实现此目的的一种非常优雅的方式。
    • 太好了,这是最好的答案!
    • 绝对是解决方案
    • 不错的答案!但我必须添加 self.searchContentsController.edgesForExtendedLayout = UIRectEdgeBottom;适用于 iOS 7
    • @stigi:我知道答案已经有几年了,如果其他人在 iOS 7 上遇到这个问题,我只是想留下一个提示 :)
    【解决方案3】:

    只是想添加到 stigi 答案。当您取消搜索并重新开始搜索时 - 搜索结果表不会对触摸做出反应,因此您需要添加下一行

    self.searchResultsTableView.alpha = 1;
    

    所以更新后的代码看起来是下一个方式

     - (void)setActive:(BOOL)visible animated:(BOOL)animated;
     {
        if(self.active == visible) return;
        if (visible) {
            [self.searchContentsController.navigationController setNavigationBarHidden:YES animated:NO];
            [super setActive:visible animated:animated];
            [self.searchContentsController.navigationController setNavigationBarHidden:NO animated:NO];
            self.searchResultsTableView.alpha = 1;
            [self.searchBar becomeFirstResponder];
        } else {
            [super setActive:visible animated:animated];
            [self.searchBar resignFirstResponder];
        }
    }
    

    【讨论】:

      【解决方案4】:

      我在我的 ViewController 上添加了自定义导航栏,该导航栏在搜索时被隐藏了,一个快速但不太好的修复是

      - (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText{
          [self.view addSubview:_navBar];
      }
      

      _navBar 是以编程方式添加的 UINavigationBar, 这样做有助于我隐藏导航栏。

      【讨论】:

        【解决方案5】:

        iOS 8 引入的新UISearchController 类有一个属性hidesNavigationBarDuringPresentation,如果你想保持导航栏可见(默认情况下它仍然是隐藏的),你可以将其设置为false。

        【讨论】:

        • 这是 iOS 8 UISearchController 的正确答案!!
        • 这应该是被接受的答案。适用于 UISearchController 的 iOS 8。
        • 这是简单的解决方案
        【解决方案6】:

        iOS 7 有点搞砸了……对我来说这很完美:

        /**
         *  Overwrite the `setActive:animated:` method to make sure the UINavigationBar 
         *  does not get hidden and the SearchBar does not add space for the statusbar height.
         *
         *  @param visible   `YES` to display the search interface if it is not already displayed; NO to hide the search interface if it is currently displayed.
         *  @param animated  `YES` to use animation for a change in visible state, otherwise NO.
         */
        - (void)setActive:(BOOL)visible animated:(BOOL)animated
        {
            [[UIApplication sharedApplication] setStatusBarHidden:YES];
            [self.searchContentsController.navigationController setNavigationBarHidden:YES animated:NO];
        
            [super setActive:visible animated:animated];
        
            [self.searchContentsController.navigationController setNavigationBarHidden:NO animated:NO];
            [[UIApplication sharedApplication] setStatusBarHidden:NO];
        }
        

        显示/隐藏状态栏的原因

        【讨论】:

          【解决方案7】:

          正如 jrc 指出的那样,“从控制任何 UISearchBar 中解开 UISearchDisplayController”似乎对我有用。如果我在创建 UISearchDisplayController 时将 nil 作为参数传递,则导航栏始终保持可见:

          searchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar:nil contentsController:self];
          

          【讨论】:

            【解决方案8】:

            这似乎为我解决了这个问题。在 iOS5/6.1 中测试。我看不到任何视觉问题。

            - (void)viewDidAppear
            {
                [super viewDidAppear];
                [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillAppear:) name:UIKeyboardWillShowNotification object:nil];
            }
            
            -(void)viewWillDisappear:(BOOL)animated{
                [super viewWillDisappear:animated];
                [[NSNotificationCenter defaultCenter] removeObserver:self];
            }
            
            - (void)keyboardWillAppear:(NSNotification *)notification
            {
                [self.navigationController setNavigationBarHidden:NO animated:NO];
            }
            
            -(void)viewDidLayoutSubviews{
                [self.navigationController setNavigationBarHidden:NO animated:NO];
            }
            

            【讨论】:

            • 只需添加其中的一部分即可为我工作:-(void)viewDidLayoutSubviews { [self.navigationController setNavigationBarHidden:NO animated:NO]; // 当用户点击搜索栏时不隐藏导航栏 }
            • 我遇到了类似的问题,当键盘出现时,我的导航栏消失了。使用上面代码的最后两种方法修复了它。
            【解决方案9】:

            非常好的解决方案,但它在 iOS6 下使我的应用程序崩溃。我必须进行以下修改才能使其正常工作。

            @implementation ICSearchDisplayController
            
                - (void)setActive:(BOOL)visible animated:(BOOL)animated
                {
                    if (visible == YES) {
                        [super setActive:visible animated:animated];
                        [self.searchContentsController.navigationController setNavigationBarHidden:NO animated:NO];
                    } else {
                        [super setActive:NO animated:NO];
                    }
                }
            

            【讨论】:

              【解决方案10】:

              @Pavel 的效果非常好。但是,我试图将它放入 UIPopoverController 并且当搜索栏的文本字段成为第一响应者时,该字段中的文本会被略微推送,这看起来有点难看,所以我通过调用 super 方法来修复它 animated 设置为 NO

              【讨论】:

                【解决方案11】:

                最简单的解决方案,没有任何技巧。

                @interface MySearchDisplayController : UISearchDisplayController
                
                @end
                
                @implementation MySearchDisplayController
                
                - (void)setActive:(BOOL)visible animated:(BOOL)animated
                {
                    [super setActive: visible animated: animated];
                
                    [self.searchContentsController.navigationController setNavigationBarHidden: NO animated: NO];
                }
                
                @end
                

                【讨论】:

                • 同意,这是最简单的解决方案。只是为了完成:如果您使用的是 xib,则选择搜索显示控制器,点击身份检查器并将类更改为 MySearchDisplayController。
                • 您是否尝试过从结果导航到详细控制器并返回?这打破了我的视图布局。 iOS 6.1
                • 不适合我。我已添加但未找到 searchContentsController
                • 当您有想要显示的详细视图时,这不起作用。一旦从详细视图中单击返回,搜索栏就会滑到导航栏下方。
                • 这是正确的答案,但带有 stigi 代码(如下)。
                【解决方案12】:

                我在处理一个稍微不同的问题时遇到了这个问题。使用 UISearchDisplayController 时,我希望搜索栏位于导航栏(不在导航栏下方)。

                将搜索栏放在导航栏中并不难(参见UISearchBar and UINavigationItem)。但是,UISearchDisplayController 假定搜索栏始终位于导航栏下方,并且(如这里所讨论的)坚持在输入搜索时隐藏导航栏,因此看起来很糟糕。此外,UISearchDisplayController 使搜索栏的颜色比正常颜色浅。

                我找到了解决方案。诀窍是(反直觉地)将 UISearchDisplayController 完全从控制任何 UISearchBar 中解脱出来。如果使用 xibs,这意味着删除搜索栏实例,或者至少解开插座。然后创建自己的 UISearchBar:

                - (void)viewDidLoad
                {
                    [super viewDidLoad];
                
                    UISearchBar *searchBar = [[[UISearchBar alloc] init] autorelease];
                    [searchBar sizeToFit]; // standard size
                    searchBar.delegate = self;
                
                    // Add search bar to navigation bar
                    self.navigationItem.titleView = searchBar;
                }
                

                您需要在用户点击搜索栏(-searchBarShouldBeginEditing:)时手动激活搜索显示控制器,并在用户结束搜索时手动关闭搜索栏(-searchDisplayControllerWillEndSearch:)。

                #pragma mark <UISearchBarDelegate>
                
                - (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar {
                    // Manually activate search mode
                    // Use animated=NO so we'll be able to immediately un-hide it again
                    [self.searchDisplayController setActive:YES animated:NO];
                
                    // Hand over control to UISearchDisplayController during the search
                    searchBar.delegate = (id <UISearchBarDelegate>)self.searchDisplayController;
                
                    return YES;
                }
                
                #pragma mark <UISearchDisplayDelegate>
                
                - (void) searchDisplayControllerDidBeginSearch:(UISearchDisplayController
                *)controller {
                    // Un-hide the navigation bar that UISearchDisplayController hid
                    [self.navigationController setNavigationBarHidden:NO animated:NO];
                }
                
                - (void) searchDisplayControllerWillEndSearch:(UISearchDisplayController
                *)controller {
                    UISearchBar *searchBar = (UISearchBar *)self.navigationItem.titleView;
                
                    // Manually resign search mode
                    [searchBar resignFirstResponder];
                
                    // Take back control of the search bar
                    searchBar.delegate = self;
                }
                

                【讨论】:

                  【解决方案13】:

                  我认为最好的解决方案是自己实现 UISearchDisplayController。

                  这并不难。您只需要为您的 UIViewController 实现 UISearchBarDelegate 并包含一个 UITableView 来显示您的搜索结果。

                  【讨论】:

                    【解决方案14】:

                    尝试了另一种方法,没有继承 UISearchDisplayController。在为 UISearchDisplayController 设置委托的 UIViewController 类中,实现 searchDisplayControllerDidBeginSearch: 并添加使用

                    [self.navigationController setNavigationBarHidden:NO animated:YES];
                    

                    帮我搞定了,希望对你有帮助。

                    【讨论】:

                    • 这比公认的答案要简单得多。它也对我有用。
                    • 当用户关注文本字段时,导航栏再次上下滑动。使用动画:NO,它会弹回原位。两种选择看起来都很糟糕。
                    • 有什么解决办法吗?
                    【解决方案15】:

                    以上答案对我来说不太合适。我的解决方案是让 UISearchDisplayController 认为没有 UINavigationController。

                    在您的视图控制器中,添加此方法

                    - (UINavigationController *)navigationController {
                        return nil;
                    }
                    

                    这对我来说没有任何副作用,尽管这似乎是一个非常糟糕的主意...如果您需要使用导航控制器,请使用 [super navigationController]

                    【讨论】:

                    • 我阅读了所有建议的解决方案,这是迄今为止最简单和最好的。
                    • 我得到:*** 在点击取消按钮时 -[UISearchDisplayController setActive:animated:] 中的断言失败。
                    • 通过调用 [self.searchDisplayController setActive:NO animated:NO] 解决了这个问题;在 - (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar
                    • 这适用于 iPad 上的 iOS 7。但是,我添加了一些代码,使其仅在搜索显示控制器调用它并且它在 ipad 上时才返回 nil,否则它会正常运行。 pastebin.com/6pJ2WWsy
                    • @KhantThuLinn 使用[super navigationController] 而不是self.navigationController
                    猜你喜欢
                    • 2013-05-25
                    • 1970-01-01
                    • 2013-12-04
                    • 2014-12-05
                    • 1970-01-01
                    • 2014-10-26
                    • 2021-06-28
                    • 1970-01-01
                    • 2011-01-21
                    相关资源
                    最近更新 更多