UISearchBar忽略程序化的约束条件

3
我正在尝试构建一个ViewController子类,利用UISearchController显示结果。该视图具有一个输入字段,我希望将其动画化到屏幕顶部,以便用户有最大的空间查看结果。
我使用一个UIView构建了一个概念验证,该UIView包装了一个搜索栏drop-in组件,并在Storyboard中设置它们的顶部、前导、尾随和底部约束相等。以下代码负责动画不同的移动:
- (void)keyboardWillAppear:(NSNotification*)notification {
    self.labelToSearchBarSpaceConstraint.active = NO;
    self.searchBarAtTopConstraint.active = YES;
    self.searchBarLeadingSpaceConstraint.constant = 0;
    self.searchBarTrailingSpaceConstraint.constant = 0;

    [UIView animateWithDuration:[notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] floatValue] animations:^{
        [self.view setNeedsLayout];
        [self.view layoutIfNeeded];
    }];
}

- (void)keyboardWillDisappear:(NSNotification*)notification {
    self.searchBarAtTopConstraint.active = NO;
    self.labelToSearchBarSpaceConstraint.active = YES;
    self.searchBarLeadingSpaceConstraint.constant = 20;
    self.searchBarTrailingSpaceConstraint.constant = 20;

    [UIView animateWithDuration: [notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] floatValue] animations:^{
        [self.view setNeedsLayout];
        [self.view layoutIfNeeded];
    }];
}

我尝试切换到程序创建的 UISearchControllerUISearchBar。以下代码设置了我认为与在 Storyboard 中等效的关系:

self.definesPresentationContext = YES;

self.searchController = [[UISearchController alloc] initWithSearchResultsController:nil];
UISearchBar* searchBar = self.searchController.searchBar;
searchBar.translatesAutoresizingMaskIntoConstraints = NO;
[self.searchBarView addSubview:searchBar];

[NSLayoutConstraint constraintWithItem:searchBar attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.searchBarView attribute:NSLayoutAttributeTop multiplier:1.0 constant:0.0].active = YES;
[NSLayoutConstraint constraintWithItem:searchBar attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.searchBarView attribute:NSLayoutAttributeLeading multiplier:1.0 constant:0.0].active = YES;
[NSLayoutConstraint constraintWithItem:searchBar attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self.searchBarView attribute:NSLayoutAttributeTrailing multiplier:1.0 constant:0.0].active = YES;
[NSLayoutConstraint constraintWithItem:searchBar attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.searchBarView attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0.0].active = YES;

然而,用这种方式完成时,UISearchBar对象不遵守约束条件。当容器向上动画时,搜索栏飞出页面。为什么会发生这种情况?
小更新:我注意到在NSLayoutConstraint的文档中将其活动属性设置为YES而不是显式添加,但行为完全相同。更新代码以匹配。
1个回答

2

当我将UISearchController的searchBar添加到UITableView的头部视图时,遇到了类似的问题。

在用户选择searchBar后,当动画约束容纳UITableView的containerView时,它不会跟随容器视图移动。

在我的情况下,似乎在调用委托方法didPresentSearchController:(UISearchController *)searchController之后,searchBar的超级视图是UISearchBarContainerView而不是UITableView的头部视图。

在动画之前将其重新添加回原始的头部视图可以帮助我解决这个问题。

-(void)didPresentSearchController:(UISearchController *)searchController {

    NSLog(@"did present search controller");

    self.tableView.tableHeaderView = self.searchController.searchBar;

    ...animation...

}

看起来这是一个相当不寻常的解决方案,但它实际上可行,谢谢!但有时会短暂闪烁 - 有什么解决办法吗?didPresentSearchController可能是在UISearchBarContainerView中显示后最早调用的方法。 - Stefan Wittwer

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