【问题标题】:Add filter button to UISearchController将过滤器按钮添加到 UISearchController
【发布时间】:2016-01-27 12:35:44
【问题描述】:

我想在UISearchController 内的searchBar 旁边添加一个“过滤器”或“排序”按钮。我已经尝试将UIButtonsearchbar 添加到UIView 并将其设置为我的UITableView tableView.tableHeaderView 这不起作用,因为tableView.tableHeaderView 仅在关闭控制器时才设置回UISearchBar .这是我希望它看起来如何的示例:

【问题讨论】:

  • 您使用搜索控制器有什么特殊原因吗?您是否愿意不使用它并直接过滤表格视图?
  • 原因纯粹是光学上的。所以我什么都可以
  • 我应该更具体一点,您已经有一个表格视图,您愿意只过滤它还是使用一个特别不同的视图来呈现搜索结果/想要搜索控制器覆盖功能?
  • 我已经有一个 tableView,我很高兴只是过滤它
  • 这个问题太宽泛,缺少MCVE

标签: ios swift uitableview uisearchbar uisearchcontroller


【解决方案1】:

我可以用几行代码创建一个搜索过滤器。希望对你有帮助。

*我选择了书签按钮来应用过滤器图标;因为我已经使用取消按钮进行自定义操作。

首先,您必须委托 searchBar 来处理书签按钮的点击操作。 然后你应该如下设置属性。如果你想给自定义位置(默认位置是右侧),你需要setPositionAdjustment。

searchController.searchBar.delegate = self
searchController.searchBar.showsBookmarkButton = true
searchController.searchBar.setImage(UIImage(named: "Sort"), for: .bookmark, state: .normal)
// MARK: You may change position of bookmark button.
//searchController.searchBar.setPositionAdjustment(UIOffset(horizontal: 0, vertical: 0), for: .bookmark)

然后,覆盖 VC 中的 searchBarBookmarkButtonClicked 函数。您可以在此方法中处理点击事件。

func searchBarBookmarkButtonClicked(_ searchBar: UISearchBar) { //showAlert, presentVC or whatever you want here }

此外,如果您想在搜索控制器处于活动状态时隐藏书签按钮,您需要在 updateSearchResults 方法中应用控件。

if searchController.isActive {
    searchController.searchBar.showsBookmarkButton = false
} else {
    searchController.searchBar.showsBookmarkButton = true
}


当 searchController 未激活时:


当 searchController 处于活动状态时:

【讨论】:

  • 很好的解决方案!谢谢。
  • 如何为图像着色?我的只是灰色的。
  • @TiloDelau 我认为您的导航色调颜色是默认的(灰色)。您可以根据需要更改状态栏的颜色。
  • @Ali 我正在使用 UIBarButtonItem.appearance().tintColor。还尝试了 searchController.searchBar.barTintColor = UIColor.white。两者都不起作用。我可以让取消(和后退按钮)具有特定的颜色,但这不会。我在状态栏和搜索栏中进行了很多调整,但我无法定位它。并且更愿意专门针对它以显示某些过滤器已被选中并处于活动状态。也试过 //UINavigationBar.appearance().tintColor
【解决方案2】:

您可以通过在 SearchBar 旁边添加自己的按钮来保持简单,而不是自定义 UISearchBar 并使事情复杂化。

使用

将 SearchBar 的 显示取消按钮 选项设置为否
self.searchBar.showsCancelButton = true

取消选中 显示取消按钮 用于 StoryBoard 中 SearchBar 的选项

在 SearchBar 旁边添加自己的按钮,如下所示

然后相应地将 IBaction 添加到按钮并在其中执行您的操作。

同样在理想情况下,不建议将此视图放在tableview的Header中。 如果它在tableview之上,Apple也跟着它会更好。

【讨论】:

  • 这与 UISearchController 一起使用时会出现问题。激活时,搜索栏视图会从其父视图中移除并放置在其他所有内容之上以保持粘性。因此,当搜索处于活动状态时,自定义按钮消失了......
  • 我在没有 UISearchController 的情况下尝试了这种方法,但有时取消按钮不再起作用。 searchBar 不再调用searchBarCancelButtonClicked,而是再次获得焦点:/
【解决方案3】:

我尝试了很多方法来自定义搜索栏,但没有任何帮助我终于找到了满足您要求的方法

let mysearchController = UISearchController(searchResultsController: nil)
    mysearchController.searchBar.showsCancelButton = true
    mysearchController.searchBar.barStyle = UIBarStyle.Black
    for var subView1 in mysearchController.searchBar.subviews{
        for var subView2 in subView1.subviews{
            if subView2 .isKindOfClass(UIButton){
                let customizedCancelButton:UIButton = subView2 as! UIButton
                customizedCancelButton.enabled = true
                customizedCancelButton.setTitle("", forState: UIControlState.Normal)
                 let image1 = UIImage(named: "Sort")
                customizedCancelButton.setBackgroundImage(image1, forState: UIControlState.Normal)
                customizedCancelButton.addTarget(self, action: "sort", forControlEvents: UIControlEvents.TouchUpInside)
            }
        }
    }

上面的代码很容易理解。

    func sort(){
       print("sort button fired!!!")
    }

【讨论】:

    【解决方案4】:

    针对 iOS 13 进行了更新,支持早期版本的 iOS,基于 Gokul G 答案。

    在项目中添加扩展文件——UISearchControllerCancelButton.swift (View on gist.github.com):

    extension UISearchController {
        func cancelButton() -> UIButton? {
            if #available(iOS 13.0, *) {
                return findCancelButton13()
            }
            return findCancelButtonOld()
        }
    
        func findCancelButtonOld() -> UIButton? {
            for subView in searchBar.subviews {
                for v in subView.subviews {
                    if let button = v as? UIButton {
                        return button
                    }
                }
            }
            return nil
        }
    
        @available(iOS 13.0, *)
        func findCancelButton13() -> UIButton? {
            for subView in searchBar.subviews {
                for v in subView.subviews {
                    for b in v.subviews {
                        if let button = b as? UIButton {
                            return button
                        }
                    }
                }
            }
            return nil
        }
    }
    

    用途:

    let controller = UISearchController(searchResultsController: nil)
    controller.searchBar.showsCancelButton = true
    
    if let button = controller.cancelButton() {
        // Customize button
        let iconImage = UIImage(named: "yourIconName")
        button.isEnabled = true
        button.setTitle("", for: .normal)
        button.setBackgroundImage(iconImage, for: .normal)
        button.addTarget(self, action: #selector(yourMethodName), for: .touchUpInside)
    }
    

    按键触摸事件的方法声明:

    @objc func yourMethodName() {
        print("Cancel button tap")
    }
    

    【讨论】:

    • 我尝试使用此方法,但我的完成按钮确实显示
    【解决方案5】:

    我会失去搜索控制器,它没有提供您真正想要的任何功能,并且您需要提供的额外视图/VC 增加了复杂性/代码重复。

    您现有的表格视图已经拥有您需要的一切,因为它有一个数据源。那是一个数组或一个 FRC。如果是数组,则可以将数组的内容替换为过滤后的内容,如果是 FRC,则可以更改谓词。

    注意:在数组的情况下,有 2 个数组引用,1 个指向一个包含所有未过滤项的数组,另一个指向同一数组的初始引用 - 第二个引用用于填充表视图。然后,当您过滤时,您会创建一个仅包含过滤项的新数组,并将第二个引用指向该数组。

    您无需实现搜索控制器委托方法,而是实现搜索栏委托方法并使用它来触发过滤和重置。

    现在您已经摆脱了搜索控制器,您也没有切换表格视图,因此您只有 1 个电视和 1 个标题视图。现在没有理由更改标题视图,一切正常。

    【讨论】:

    • 我不知道你明白我在找什么。我不想知道如何过滤 tableView,而是想知道如何设法在搜索栏旁边获得一个过滤按钮(理想情况下在搜索控制器中)
    • 这就是我询问丢失搜索控制器的原因。您遇到的问题是搜索控制器呈现不同的视图,因此标题的配置不同。您应该能够在另一个视图上设置另一个标题。我发现搜索控制器只是增加了复杂性而没有什么真正的好处。如果您只有 1 个视图,则您有 1 个易于配置的标题,并且焦点管理也很简单。
    猜你喜欢
    • 2017-04-27
    • 2019-06-22
    • 2011-07-03
    • 1970-01-01
    • 1970-01-01
    • 2021-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多