不能将UISearchController与UICollectionView一起使用?

时间:2014-07-25 18:29:47

标签: ios uicollectionview uisearchbar

在WWDC 2014演讲中#34;内部展示控制器"演示者展示了如何在UITableView中设置UISearchController。他们通过设置searchController的searchBar框架,然后将其设置为tableView的tableHeaderView来完成此操作。不幸的是,对于UICollectionView,没有相当于tableHeaderView的东西。使用UISearchDisplayController,这很简单:创建一个UISearchBar并将其添加到自定义UICollectionView节头,然后使用搜索栏初始化UISearchDisplayController。问题是,您无法使用UISearchBar初始化UISearchController,甚至设置searchBar,因为它是一个只读属性。我想我真正的问题是,我的选择是什么?有没有好的"没有UISearchDisplayController或UISearchController实现搜索的方法?

3 个答案:

答案 0 :(得分:14)

  

使用UISearchDisplayController,这很简单:创建一个UISearchBar并将其添加到自定义UICollectionView节头,然后使用搜索栏初始化UISearchDisplayController

为您创建UISearchController中的搜索栏。当您在数据源方法中询问补充视图时

- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath

将searchController.searchBar添加为补充视图的子视图。别忘了打电话

[searchController.searchBar sizeToFit]

为搜索栏指定合适的大小。

答案 1 :(得分:4)

我的第一个问题:为什么你不能翻转逻辑而不是创建搜索栏,首先创建一个UISearchController,抓住它的搜索栏并将其添加到部分标题中?

其次,集合视图布局不像表视图那么简单。搜索使用集合视图布局来猜测您的意图很困难,而表格视图非常简单。因此,在集合视图的情况下,您可以自由地向视图添加搜索栏,但将其设置为活动状态将需要一些工作。 (子类UISearchController并返回你自己的动画控制器,然后做你想要的任何动画。或者只是在子类上实现UIViewControllerAnimatedTransitioning中的方法而不要调用super,两者都应该工作)

您可能想要尝试的是让屏幕外显示搜索栏。这是一个内置动画,UISearchController在调用setActive:时支持,搜索栏不在视图层次结构中的任何位置。日历就是这样......它非常酷。您可以将搜索缩小为驱动演示文稿的图标,而不是始终存在巨大的搜索栏。

最后,肯定会有错误。 请提交错误,如果您无法按照自己的想法开展工作。我知道,这是一个破纪录,但它确实是必要的。

答案 2 :(得分:0)

这里接受的答案似乎已经过时,在回答时没有牢记几件事。如下:

  1. 首先由于未提供实现,所以有人可能会猜测我们应该将UISearchController.searchbar视图作为补充视图返回,但您不能这样做,因为类型不匹配。
  2. 第二您在已出列的补充标题视图中将UISearchController.searchbar添加为子视图,但是请耐心等待,您必须从其他补充视图中删除该视图,因为该补充视图可能会重新在其他部分中使用(通常在collectionView中使用多个部分)
  3. 第三是从用户体验角度来看的。假设您只有一个部分,其中包含来自搜索控制器的搜索栏。现在,用户向下滚动到CollectionView的末尾,该顶部将不再位于屏幕顶部,因此,要进行搜索,用户必须一直向上滚动以开始搜索。

最近,我正在努力实现这种用户体验,以在具有多个部分的collectionView上进行搜索。这是我的解决方法。

在情节提要中,使用UIViewController而不是UICollectionViewController。在ViewController中,我像下面这样添加一个UIView和一个UICollectionView

---------ViewController----------
|                               |
|            UIView             |
|                               |
|===============================|
|                               |
|                               |
|                               |
|                               |
|                               |
|       UICollectionView        |
|                               |
|                               |
|                               |
|                               |
|                               |
|                               |
---------------------------------

顶部UIView具有高度限制,并固定到topleftright。底部CollectionView固定到bottomleftright,并且顶部视图和底部集合视图之间的垂直距离设置为零。顶视图的子类为FillSubView,如下所示

FillSubView.swift

import UIKit

class FillSubView: UIView {
    override func didAddSubview(_ subview: UIView) {
        subview.frame = self.bounds
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        subviews.first?.frame = self.bounds
    }
}

它的作用是,每次添加子视图或FillSubView的布局发生变化时,第一个子视图都会调整为该内容的大小。您可能会发现为什么我不使用约束来固定子视图。我的意图是将UISearchController.searchbar添加为FillSubView中的子视图。当UISearchController激活和停用后,此搜索栏将被删除并重新添加到上一个父视图中。在这种情况下,如果您严格要将搜索栏固定到FillSubView,则可以覆盖

- (void)didAddSubview:(UIView *)subview;

将子视图(搜索栏)固定到父视图(顶,底,左,右)。从超级视图中删除时,约束将被自动删除。

现在说视图控制器被子类化为MyViewController。我采用了IBOutlet,其中包括顶部UIView,CollectionView和顶部视图高度约束,如下所示:

@IBOutlet weak var searchBarContainer: UIView! // top view
@IBOutlet weak var collectionView: UICollectionView! // bottom collection view
@IBOutlet weak var searchContainerHeightConstraint: NSLayoutConstraint! // top view height constraint

然后在MyViewController中,我添加了一个函数来如下设置searchController

private func setupSearchController() {

    searchController = UISearchController.init(searchResultsController: nil)
    searchController?.searchResultsUpdater = self
    searchController?.dimsBackgroundDuringPresentation = false
    searchController?.searchBar.placeholder = "Search"

    if let searchbar = searchController?.searchBar {
        searchBarContainer.addSubview(searchbar)
        searchContainerHeightConstraint.constant = searchbar.bounds.height
    }
    definesPresentationContext = true
}

我从ViewDidLoad的ViewController重载方法中调用此方法。这里的重点是FillSubView类,它沿整个视图填充了搜索栏。

委托searchResultUpdater的实现非常普遍,只是过滤掉用户在搜索栏中键入任何文本时要显示的内容。

这样,我实现了自己的目标,并且也符合前面所述的3个问题。

希望有帮助。