UISearchController 位置错误,因为带有 tableview 插图

Posted

技术标签:

【中文标题】UISearchController 位置错误,因为带有 tableview 插图【英文标题】:UISearchController wrong position because of with tableview inset 【发布时间】:2017-06-08 13:11:18 【问题描述】:

我正在开发一个在 UITableView 上方具有自定义视图的功能,看起来 TableView 具有 contentInset。我将 SearchController 添加到 TableViewHeader 中,但是当我点击 searchTextView 时,SearchController 会随着动画(大约 20 像素)向上移动。我希望 UISearchBar 像“Constacts”一样位于 ViewController 的顶部

此屏幕截图显示了现在的情况:

这是我想要的:

我该怎么办?搜索后我需要 contentInset(用户点击取消),但在搜索过程中我不需要它。

我想提供应用示例,演示所有这些东西 -> enter link description here

【问题讨论】:

我认为这与您的约束有关,但只是为了确保它不是更简单的东西,您确定在视图控制器上设置 self.automaticallyAdjustsScrollViewInsets = false 吗?该标志通常会在表格视图上方留下一些不需要的空白。 主要问题是 - 当您设置自定义插图时 UISearchViewController 的默认动画不起作用。 automaticAdjustsScrollViewInsets 无济于事 即使我觉得那是约束问题。您是否为 tableView 提供恒定的顶部约束? @NosovPavel 请检查我的答案 【参考方案1】:

如果您使用的是故事板,您应该单击您为 tableview 设置的视图控制器或 TableView 控制器,然后转到其属性检查器并查看 ViewController 部分并检查 Extend Edges 部分位于顶栏下方。

                      **OR**

同时选中 Under Top Bars 和 Under Opaque Bars,不选中 Under Bottom Bars。

这样做:

这样做:

【讨论】:

第二个选项“Check Under Opaque Bars”解决了我出现键盘时搜索栏向下移动的问题,谢谢! 我认为你发错人了,我不是 OP :-)【参考方案2】:

尝试在界面构建器中使用Adjust Scroll View InsetsUnder Top BarsUnder Bottom Bars。我在 collectionView 上遇到了同样的问题,并且将它们关闭对我有用。您的示例项目对我有用,但是当我在这些设置之间切换时它会中断。

【讨论】:

【参考方案3】:

将下面的代码添加到viewWillAppear()

self.automaticallyAdjustsScrollViewInsets = false

【讨论】:

'automaticallyAdjustsScrollViewInsets' 在 ios 11.0 中已弃用:改用 UIScrollView 的 contentInsetAdjustmentBehavior 谢谢,你节省了我的时间!【参考方案4】:

每次触发 searchBar 开始/结束编辑时如何调整内容插入:

// MARK: - UISearchBarDelegate
func searchBarShouldBeginEditing(_ searchBar: UISearchBar) -> Bool 
    UIView.transition(with: self.tableView,
                      duration: 0.6,
                      options: .curveLinear,
                      animations: 
                        self.tableView.contentInset = UIEdgeInsets.zero
    , completion:  success in )
    return true


func searchBarTextDidEndEditing(_ searchBar: UISearchBar) 
    UIView.transition(with: self.tableView,
                      duration: 0.6,
                      options: .curveLinear,
                      animations: 
                        self.tableView.contentInset = UIEdgeInsets(top: 100, left: 0, bottom: 0, right: 0)
    , completion:  success in )

【讨论】:

【参考方案5】:

    创建一个临时的 UISearchBar 并将其分配为 tableHeaderView

    searchbar   =   UISearchBar(frame: CGRect(x: 0, y: 0, width: 375, height: 44))
    searchbar?.delegate =   self
    tableView.tableHeaderView = searchbar
    

    在点击 searchBar 之前,呈现 UISearchController 以复制动画

    func searchBarShouldBeginEditing(_ searchBar: UISearchBar) -> Bool 
    
        if searchBar == searchbar 
    
           self.tableView.tableHeaderView  =   nil
    
           UIView.animate(withDuration: 0.33, animations: 
               // 64+44 is due because the navigation gets hidden and also because of the temp searchBar as tableHeaderView
               self.tableView.contentInset =   UIEdgeInsets(top: 64+44, left: 0, bottom: 0, right: 0)
           , completion:  _ in
    
           )
           self.present(searchController, animated: true, completion: nil)
       
    
       return false
    
    
    

    最后在 UISearchController searchBar 的取消按钮上重置 tableView contentInset

    func searchBarCancelButtonClicked(_ searchBar: UISearchBar) 
        if searchBar == searchController.searchBar 
            UIView.animate(withDuration: 0.33, animations: 
                self.tableView.contentInset =   UIEdgeInsets(top: 100+44, left: 0, bottom: 0, right: 0)
            , completion:  _ in
    
            )
    
            self.searchbar?.isHidden    =   false
            self.tableView.tableHeaderView  =   self.searchbar
        
    
    

【讨论】:

【参考方案6】:

我对附加在 UIViewController 中的 UISearchBar 也有同样的问题,搜索栏下方是 UICollectionView,因此错误报告是如果我向下滚动列表 (UICollectionView),则默认情况下操作系统会自动调整滚动视图.

我们可以禁用这样的行为,通常在 viewDidLoad 或 viewWillAppear 下的视图设置函数中:

        if #available(iOS 11.0, *) 
            self.collectionView.contentInsetAdjustmentBehavior = .never
         else 
            automaticallyAdjustsScrollViewInsets = false
        

参考:

https://***.com/a/44880387/1477298 https://developer.apple.com/documentation/uikit/uiscrollview/contentinsetadjustmentbehavior https://developer.apple.com/documentation/uikit/uiviewcontroller/1621372-automaticallyadjustsscrollviewin#

【讨论】:

【参考方案7】:

我有类似的问题,我通过将edgesForExtendedLayout 设置为 none 来解决它, 但是在研究之后,解决方案可能会有所不同,具体取决于您对层次结构的实现,您可能希望从情节提要中取消选中 Extend Edges Under Top Bar

【讨论】:

感谢您的回答,但我尝试这样做。请看我上面的评论【参考方案8】:

首先,我查看了您链接的两个项目,在 Objective-C 版本中没有内容插入,它只是一个普通的表格视图。

至于你的问题,让我确定我理解。这是您需要的:

    表格视图 表格视图上方的图片不改变位置,不滚动,只是停留在那里 位于表格顶部但固定图像下方的搜索栏 当用户搜索时,隐藏图片并将表格视图一路向上 当用户完成搜索后,您希望表格向下,以便图像可以再次显示在顶部

对吗?

假设这是真的,这是我的想法。

首先,我会放弃 UITableViewController 并将其更改为 UIViewController。将表视图添加为子视图并从视图控制器管理其位置。这意味着您不会乱用内容插图,只需将表格放在图像下方即可。我不确定您是否想要图像上方或下方的搜索栏,但假设它在下方,仍然只是将其作为表格视图的标题,当它变为活动状态时,只需为表格视图和图像设置动画以向上移动直到图像消失了,表格视图位于顶部。如果您希望搜索栏位于图像上方,则不要将其添加到表格视图中,而是将其添加为主视图的子视图,与所有内容分开,并通过代码管理其位置,而不是让操作系统处理它.此外,搜索控制器可能存在问题,我没有使用太多,所以我不确定,但您最好使用 UISearchBar 并自己处理所有搜索。

祝你好运!

【讨论】:

【参考方案9】:

我认为您的 YourVC(具有 SearchBar 和 Table View 的 VC)嵌入在 NavigationController 中,或者只是由嵌入的 VC 推送。

请看一下这个Sample,我为你创建的。

注意:

    放置CustomView高度约束(Top:0,Leading:0,trailing:0,Height:60)。 将搜索栏放在自定义视图中,将搜索栏上的约束添加为 (Top:20,leading:0,trailing:0,bottom:0)。 对 searchBar 使用 Minimal SearchBarStyle。 在搜索栏中启用“取消”按钮。 使用颜色选择器为自定义视图提供与搜索栏颜色相同的背景颜色。 将 TableView 放在 customView 下方,并将约束设置为(自定义视图的垂直间距:0,前导:0,尾随:0,底部:0)。 取消选中“调整滚动视图插图”,如下图所示。

希望这能解决您的问题。

【讨论】:

不,它没有帮助,因为它不是我要寻找的。你的样品没有像我预期的那样工作。 searchBar 没有默认动画,也没有插入【参考方案10】:

实际上,视图控制器正在尝试将您的 UITableView 的内容插入自动调整为导航栏高度。

取消选中Adjust Scroll View Insets 应该可以解决您的问题。我在使用故事板时也遇到了这个问题。

【讨论】:

【参考方案11】:

您似乎试图在 ViewController 中调整 tableView,如果是这种情况,您可以通过在您的 tableView 对象和故事板中的 navigationBar 下添加空视图并给它这样的约束来解决它。

我知道这是某种 hackie,但这会解决你的问题,为了实现我在项目中使用的 searchController,它工作正常

var searchController: UISearchController?

override func viewDidLoad() 
    super.viewDidLoad()

    searchController?.isActive = true
    searchController = initSearchController()


func initSearchController() -> UISearchController 
    let searchController = UISearchController(searchResultsController: nil)
    searchController.searchResultsUpdater = self
    searchController.searchBar.delegate = self
    searchController.hidesNavigationBarDuringPresentation = true
    searchController.dimsBackgroundDuringPresentation = false
    definesPresentationContext = true


    searchController.searchBar.searchBarStyle = .minimal
    searchController.searchBar.sizeToFit()
    self.tableView.tableHeaderView = searchController.searchBar
    tableView.contentOffset = CGPoint(x: 0, y: 
    searchController.searchBar.frame.size.height)
    return searchController

希望这会有所帮助

【讨论】:

【参考方案12】:

我相信您使用的是导航控制器,它在 tableView 上方引入了一个导航栏。所以你需要做两件事。

    使用隐藏导航栏,

    self.navigationController.navigationBarHidden = YES;//(目标c) self.navigationController.navigationBarHidden = true;//(swift)

    调整tableview的frame,将origin.y从0改为-44(因为navigationBar的高度是44),如下图,

【讨论】:

【参考方案13】:

我刚刚将self.extendedLayoutIncludesOpaqueBars 设置为 true 解决了我的问题。

【讨论】:

以上是关于UISearchController 位置错误,因为带有 tableview 插图的主要内容,如果未能解决你的问题,请参考以下文章

在 Swift 中更改 UISearchController 的位置

激活和停用 UISearchController 时 UITableView 在位置之间跳转

UISearchController + UICollectionView 错误

UISearchController 模态表示样式错误

UISearchController 以模态方式存在时的错误行为

UISearchController 滑动时错误的动画然后消失