iOS 7 UISearchDisplayController搜索栏在搜索时重叠状态栏

66

我正在更新我的iOS 7应用程序,我正在调整所有的视图以适应新的透明状态栏(我的应用程序仍将使用不透明的导航栏)。

调整每个视图的状态栏相对容易,除了一个与UISearchBar连接到UISearchDisplayController的视图控制器中出现的主要问题。

搜索栏似乎正常显示,如下所示:

Search Bar

问题在于,一旦我开始搜索,导航栏消失(应该是这样),但其他所有东西也会向上移动以重叠状态栏:

Broken Search Bar

这显然不是预期效果,因为屏幕变暗发生在搜索栏下方20个像素处,而搜索栏应该结束。

iOS 7中是否有内置解决方案?我不想每次用户开始和结束搜索时都手动调整每个视图的框架。

谢谢!


我想指出,我在另一个视图中有一个搜索显示控制器和搜索栏,附加到UITableViewController上,可以正常过渡。也许这与问题有关? - desmondhume
我也有同样的问题,这个话题有更新吗? - David L
我有相同的设置和相同的问题。 - Hackmodford
我认为这与成为导航控制器层次结构中的第一个视图有关。例如,这仅会发生在与选项卡栏控制器上的选项卡相关联的视图中。 - Hackmodford
12个回答

88

将以下代码放入viewDidLoad方法中,问题得到了解决:

self.edgesForExtendedLayout = UIRectEdgeNone;

20
如果你选择这个方案,假设你的搜索栏在屏幕顶部,那么self.edgesForExtendedLayout = UIRectEdgeLeft | UIRectEdgeBottom | UIRectEdgeRight;可能是一个更好且更通用的解决方案。(这将保留其他边缘的扩展布局,对于具有屏幕底部模糊效果的工具栏等内容非常重要。) - smileyborg
4
只需检查 [self respondsToSelector:@selector(edgesForExtendedLayout)] 即可避免在 < iOS 7 上崩溃。 - richy
@richy 没有理解你的意思。如果在 Xcode 4.x 中打开相同的代码,我会得到错误。 - Jayprakash Dubey
1
Jayprakash,XCode 4.x仅支持iOS6.x及以下版本,因此您需要执行if ([self respondsToSelector:@selector(edgesForExtendedLayout)]){self.edgesForExtendedLayout = UIRectEdgeNone;} - richy
1
直到我发现视图控制器有一个SearchDisplayControllers的引用,这才对我起作用。一旦我在IB中链接了它,它就可以工作了! - Megasaur
显示剩余2条评论

21

感谢hodade将我引向正确的方向!你的解决方案有效,但它只移动了搜索栏的框架,其他子视图仍停留在错误的位置。我所做的唯一更改就是将我的所有子视图移动到我的视图中,并进行动画处理。

谢谢!

-(void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller {
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
        CGRect statusBarFrame =  [[UIApplication sharedApplication] statusBarFrame];
        [UIView animateWithDuration:0.25 animations:^{
            for (UIView *subview in self.view.subviews)
                subview.transform = CGAffineTransformMakeTranslation(0, statusBarFrame.size.height);
        }];
    }
}

-(void)searchDisplayControllerWillEndSearch:(UISearchDisplayController *)controller {
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
        [UIView animateWithDuration:0.25 animations:^{
            for (UIView *subview in self.view.subviews)
                subview.transform = CGAffineTransformIdentity;
        }];
    }
}

1
这个和hodade的回答都没有帮到我。它仍然会自动移动搜索栏。 - Hackmodford
1
经过进一步的审查,这似乎是一个时间问题。使用DidBeginSearch将使其在状态栏下方进行动画处理,然后再向下移动一些... - Hackmodford
在某些情况下,它在iOS7中对我而言可以正常工作,但在某些情况下它无法工作。这是为什么?我们为什么需要编写上述代码? - Sandeep

13

你可能正在使用非半透明的导航栏? 如果是这样,这将解决问题。

- (void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller {
    self.navigationController.navigationBar.translucent = YES;
}

- (void)searchDisplayControllerDidEndSearch:(UISearchDisplayController *)controller {
    self.navigationController.navigationBar.translucent = NO;
}

1
self.edgesForExtendedLayout = UIRectEdgeNone; 在我的情况下不起作用,谢谢 @tachiba - Kanhaiya Sharma

7

只需将以下代码放置在-(void) ViewDidLoad中。它适用于iOS 7及更高版本。

if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1) {
    self.edgesForExtendedLayout = UIRectEdgeNone;
}

更新:

if(SYSTEM_VERSION_GREATER_THAN(@"6.1")) {
    self.edgesForExtendedLayout = UIRectEdgeNone;
}

非常感谢@Salim!这个解决方案适用于在iPad/iPhone6+上作为弹出窗口打开的UIViewController中嵌入的UISearchBar。 - AlBirdie

6
我用以下代码解决了这个问题。
    - (void) viewDidLayoutSubviews
{
         if(floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1)
        {
            CGRect viewBounds = self.view.bounds;
            CGFloat topBarOffset = self.topLayoutGuide.length;
            viewBounds.origin.y = topBarOffset * -1;
            self.view.bounds = viewBounds;
        }
}

我猜这应该放在 UISearchDisplayController 的子类中?它没有一个 view 属性。 - osxdirk
谢谢,这对我很有帮助。 - Tunvir Rahman Tusher

6

这似乎描述了我遇到的问题,希望它能帮助我的前任。

  1. Subclass your SearchDisplayController that's been added to your UIViewController/UITablewViewController,

  2. Add something like this to its implementation:

     - (void)setActive:(BOOL)visible animated:(BOOL)animated
    {
        [super setActive:visible animated:animated];
    
        [self.searchContentsController.navigationController setNavigationBarHidden: NO animated: NO];
    
        CGRect frame = self.searchResultsTableView.frame;
        frame.origin.y = CGRectGetHeight(self.searchContentsController.navigationController.navigationBar.frame);
    
        frame.size.height = CGRectGetHeight(frame) - CGRectGetMinY(frame);
    
        self.searchResultsTableView.frame = frame;
    
        frame = self.searchBar.frame;
        self.searchBar.frame = frame;
    
        [self.searchContentsController.view insertSubview:self.searchBar aboveSubview:self.searchResultsTableView];
    
    }
    

太棒了,这在模拟器中可以在iOS7(和8)上运行。不知道为什么这不更受欢迎。 - minerat

5

我认为将以下代码添加到viewDidLoad中可能会有帮助:

if([self respondsToSelector:@selector(setEdgesForExtendedLayout:)])
{
    self.edgesForExtendedLayout = UIRectEdgeNone;

}

或者实际上设置标志以调整它们以适应表视图。 - pronebird

3

2

在我的情况下,搜索栏下面的视图放置正确,只有搜索栏重叠在状态栏上。在这种情况下,下面的代码可以正常工作:

- (void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller {        
    if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")) {
        CGRect statusBarFrame =  [[UIApplication sharedApplication] statusBarFrame];
        CGRect frame = self.searchBar.frame;
        frame.origin.y += statusBarFrame.size.height;
        self.searchBar.frame = frame;
    }
}

- (void)searchDisplayControllerWillEndSearch:(UISearchDisplayController *)controller {
    if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")) {
        CGRect statusBarFrame =  [[UIApplication sharedApplication] statusBarFrame];
        CGRect frame = self.searchBar.frame;
        frame.origin.y -= statusBarFrame.size.height;
        self.searchBar.frame = frame;
    }
}

希望这对其他人有用


0

对已添加到您的UIViewController/UITablewViewController中的SearchDisplayController进行子类化,并将以下内容添加到其实现中 -

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接