在 Swift 的标头中使用分段控件更改 UICollectionView 的内容

Posted

技术标签:

【中文标题】在 Swift 的标头中使用分段控件更改 UICollectionView 的内容【英文标题】:Changing content of UICollectionView with segmented Control in the header in Swift 【发布时间】:2017-05-24 09:28:45 【问题描述】:

几个小时以来我一直试图解决这个问题,但没有找到合适的解决方案。我想在标题中有一个带有分段控件的自定义 UICollectionView。更改分段控制索引应该以不同方式呈现单元格。到目前为止,我可以在我的 collectionView 的标题中显示分段控件,但是在我的 UserSearchHeader 中更改 collectionView 的内容不起作用。

我创建了一个名为 UserSearchController 的自定义 UICollectionView,它是 UICollectionView 的子类,符合 UICollectionViewDelegateFlowLayout 协议。

        class UserSearchController: UICollectionViewController, 
              UICollectionViewDelegateFlowLayout, UISearchBarDelegate  ....

我的自定义 collectionView UserSearchController 有一个自定义标题 (UserSearchHeader) 和自定义单元格 (UserSearchCell)。

  collectionView?.register(UserSearchCell.self, forCellWithReuseIdentifier: cellId)
  collectionView?.register(UserSearchHeader.self, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "headerId")

UserSearchHeader 包含分段控件。

   class UserSearchHeader: UICollectionViewCell 

var segmentedControl: UISegmentedControl = 
    let sc = UISegmentedControl(items: ["Username", "Hashtag"])
    sc.translatesAutoresizingMaskIntoConstraints = false
    sc.tintColor = UIColor.black
    sc.selectedSegmentIndex = 0 // automatically highlight
    //  sc.addTarget(self, action: #selector(segmentedChange), for: .valueChanged)
    return sc
() .....

如果 segmentedIndex 为 0,我想用 UserSearchCell 类渲染单元格,如果 segmentedIndex 为 1,我想用不同的 cellClass 渲染它(单击分段控件)。如何使用这些不同的类实现这种行为。我应该在 UserSearchController 内部的方法中使用 cellForItem 来检查分段控件的状态。但是,当在 UserSearchHeader 类中定义分段控件时,我该怎么做。

       override func collectionView(_ collectionView: 
    UICollectionView, cellForItemAt indexPath: IndexPath) -> 
  UICollect. ionViewCell  if segmentedControl.segmentedIndex = 0 ....

【问题讨论】:

是的,您可以轻松地执行此操作,更改选定索引后,您需要重新加载集合视图,并在索引路径的 cellforrow 中检查选定索引是否为零返回单元格1,如果选定索引为 1,则返回单元格2 我试过了,但这不起作用,因为segmentedControl是在UserSearchHeader中定义的。内容没有变化,因为分段控件的targetAction没有执行 OK 然后制定协议,一旦选择的索引更改就会通知您,并且还会传递您选择的索引。 谢谢,但我不知道该怎么做,你能根据我的课程给我一个简短的例子吗?它会对我有很大帮助。 好的,请给我发送代码,如果可以的话,我会这样做 【参考方案1】:

尝试使用 scopeButtonTitles 属性?

mySearchController.searchBar.scopeButtonTitles = ["Username", "Hashtag"]

查看this question 了解更多详情。基本上你使用

func searchBar(_ searchBar: UISearchBar, selectedScopeButtonIndexDidChange selectedScope: Int)  
    // respond to your scopeBar selection here
    switch selectedScope 
    case 0:
        print("Username tab selected")
        // do your stuff for Username here
    case 1:
        print("Hashtag tab selected")
        // do your stuff for Hashtag here
    default:
        print("Someone added a tab!")
        // you shouldn't have more than 2 tabs

编辑: 请在下面找到最初提供的链接中描述的缺失部分。无需从 NIB 添加标头。

首先,为搜索和结果控制器添加属性:

typealias ResultVC = UserResultController //The class to show your results
var searchController: UISearchController! 
var resultController: ResultVC? 

然后,在viewDidLoad 中添加:

// Search Results 
resultController = ResultVC() 
setupSearchControllerWith(resultController!) 
if #available(ios 9.0, *)  
    searchController?.loadViewIfNeeded() 
 

那么你需要把这个函数添加到你的类中:

func setupSearchControllerWith(_ results: ResultVC)  
    // Register Cells 
    results.tableView.register(TableCell.self, forCellReuseIdentifier: "\(TableCell.self)") 
    results.tableView.register(UINib(nibName: "\(TableCell.self)", bundle: Bundle.main), forCellReuseIdentifier: "\(TableCell.self)") 

  // We want to be the delegate for our filtered table so didSelectRowAtIndexPath(_:) is called for both tables. 
    results.tableView.delegate = self 

    searchController = UISearchController(searchResultsController: results) 

    // Set Scope Bar Buttons 
    searchController.searchBar.scopeButtonTitles = ["Comics only", "Digital too"] 

    // Set Search Bar 
    searchController.searchResultsUpdater = self 
    searchController.searchBar.sizeToFit() 
    tableView.tableHeaderView = searchController.searchBar 

    // Set delegates 
    searchController.delegate = self 
    searchController.searchBar.delegate = self    // so we can monitor text & scope changes 

    // Configure Interface 
    searchController.dimsBackgroundDuringPresentation = false 
    searchController.hidesNavigationBarDuringPresentation = true 
    if #available(iOS 9.1, *)  
        searchController.obscuresBackgroundDuringPresentation = false 
      

    // Search is now just presenting a view controller. As such, normal view controller 
    // presentation semantics apply. Namely that presentation will walk up the view controller 
    // hierarchy until it finds the root view controller or one that defines a presentation context. 
    definesPresentationContext = true 
 

最后,添加我最初描述的函数:searchBar:selectedScopeButtonIndexDidChange:

【讨论】:

我的 searchBar 在我的导航栏中,当添加属性 scopeButtonTitles 时,它没有显示任何东西,只是灰色背景 如果我将搜索栏放在我的 collectionView 的标题中,它又在另一个类中,我无权访问。如何在导航栏中显示带有 scopeButtonTiles 的 searchBar。如何自动增加navigationBar的高度? 检查你的 UISearchController 的属性。在我的示例中,它称为 mySearchController。如您所见,searchBar 属性是您的navigationBar 的一个属性。查看 UISearchController 的属性名称以及添加 searchBar 的方式。在提供的链接中,您有一个示例。看看,因为添加 searchBar 也是单行的。 不,它不起作用,请参阅:***.com/questions/44164324/…。如何使用分段控制解决它。

以上是关于在 Swift 的标头中使用分段控件更改 UICollectionView 的内容的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Swift 的分段控件中调整 textLabel 的大小?

Swift 在尝试访问分段控制索引时抛出错误

如何在 Swift 的工具栏顶部居中分段控件?

Swift 自定义分段控件 SegmentedControl

swift Swift中的通用分段控件

Swift - 如何让分段控制锁定在屏幕顶部