tvOS SearchController,避免折叠键盘

时间:2020-06-15 07:38:50

标签: ios swift tvos apple-tv

我在tvOS中创建了一个SearchController,该视图在水平滚动的CollectionView中显示了结果。

最终结果看起来非常可怕,因为当焦点从键盘移到结果时,键盘会自动关闭。

由于没有键盘时集合视图的高度较大,因此其上的元素会在集合视图中自动重新对齐。这使UX非常混乱。

您可以在以下GIF中看到问题。将焦点从键盘上移到结果上,甚至聚焦到非预期的元素上。 (用“七个”代替“五个”)

enter image description here

有什么方法可以避免键盘崩溃?我注意到,当结果视图包含不可滚动的视图时,键盘不会折叠,但是我需要使结果可滚动。

在这里您可以找到重现该问题的代码。

import UIKit

private var items = ["One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve"]

final class MySearchViewController: UIViewController, UICollectionViewDataSource {

    override func viewDidLoad() {
        super.viewDidLoad()
        setUpView()
    }

    // MARK: - Private

    private lazy var searchContainerViewController: UISearchContainerViewController = {
        return UISearchContainerViewController(searchController: searchController)
    }()

    private lazy var searchController: UISearchController = {
        let searchController = UISearchController(searchResultsController: searchResultsController)
        return searchController
    }()

    private lazy var searchResultsController: UIViewController = {
        let layout = UICollectionViewFlowLayout()
        layout.scrollDirection = .horizontal

        let searchResultsController = UICollectionViewController(collectionViewLayout: layout)
        searchResultsController.collectionView.dataSource = self
        MyCell.register(in: searchResultsController.collectionView)
        return searchResultsController
    }()

    private func setUpView() {
        embed(viewController: searchContainerViewController, inContainerView: view)
    }

    // MARK: - UICollectionViewDataSource

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return items.count
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: MyCell.reuseIdentifier, for: indexPath) as! MyCell
        cell.titleLabel.text = items[indexPath.row]
        return cell
    }
}

class MyCell: UICollectionViewCell {

    static var reuseIdentifier: String { return String(describing: self) + "ReuseIdentifier" }

    var titleLabel: UILabel!

    public static func register(in collectionView: UICollectionView) {
        collectionView.register(MyCell.self, forCellWithReuseIdentifier: MyCell.reuseIdentifier)
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
        titleLabel = UILabel(frame: bounds)
        backgroundColor = .blue
        contentView.addSubview(titleLabel)
    }

    override func didUpdateFocus(in context: UIFocusUpdateContext, with coordinator: UIFocusAnimationCoordinator) {
        backgroundColor = isFocused ? .red : .blue
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }
}

一种避免聚焦错误元素的解决方法是将固定高度分配给CollectionView。但是这样做仍然会隐藏键盘,从而在屏幕上留下很多多余的空白空间。

因为在这种情况下隐藏键盘是没有用的。我想让它始终可见。

这是对集合视图使用固定高度的结果。

enter image description here

1 个答案:

答案 0 :(得分:3)

直到tvOS 14,苹果发布了新财产searchControllerObservedScrollViewhttps://developer.apple.com/documentation/uikit/uisearchcontroller/3584820-searchcontrollerobservedscrollvi

之前,这实际上是不可能的

通过在此属性上设置collectionView,SearchController会自动使搜索栏+键盘位置适应您的CollectionView偏移量。

您可以通过以下方式修改代码:

    private lazy var searchController: UISearchController = {
        let searchController = UISearchController(searchResultsController: searchResultsController)
        if #available(tvOS 14.0, *) {
            searchController.searchControllerObservedScrollView = (searchResultsController as? UICollectionViewController)?.collectionView
        }
        return searchController
    }()

要摆脱可为空的类型转换,只需将searchResultsController的返回类型更改为UICollectionViewController。它不会影响您的实施。