tvOS SearchController,避免折叠键盘
tvOS SearchController, avoid collapsing keyboard
我在 tvOS 中创建了一个 SearchController,它在带有水平滚动的 CollectionView 中显示结果。
最终结果看起来很糟糕,因为当焦点从键盘移到结果时,键盘会自动消失。
因为collection view的高度在没有键盘的情况下比较大,上面的元素会在collection view中自动重新对齐。这让用户体验非常混乱。
您可以在下面的 GIF 中看到问题。将焦点从键盘向下移动到结果,最终甚至会聚焦一个非预期的元素。 ("Seven" 而不是 "Five")
有什么办法可以避免键盘塌陷吗?。我注意到当结果视图包含不可滚动的视图时,键盘不会折叠,但我需要使我的结果可滚动。
在这里您可以找到重现该问题的代码。
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 分配固定高度。但是这样做,仍然隐藏了键盘,在屏幕上留下了很多多余的空白space。
因为在这种情况下隐藏键盘是没有用的。我想让它始终可见。
这是集合视图使用固定高度的结果。
直到苹果发布新的 tvOS 14 属性 searchControllerObservedScrollView
:https://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
return 类型更改为 UICollectionViewController
。它应该不会影响您的实施。
我在 tvOS 中创建了一个 SearchController,它在带有水平滚动的 CollectionView 中显示结果。
最终结果看起来很糟糕,因为当焦点从键盘移到结果时,键盘会自动消失。
因为collection view的高度在没有键盘的情况下比较大,上面的元素会在collection view中自动重新对齐。这让用户体验非常混乱。
您可以在下面的 GIF 中看到问题。将焦点从键盘向下移动到结果,最终甚至会聚焦一个非预期的元素。 ("Seven" 而不是 "Five")
有什么办法可以避免键盘塌陷吗?。我注意到当结果视图包含不可滚动的视图时,键盘不会折叠,但我需要使我的结果可滚动。
在这里您可以找到重现该问题的代码。
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 分配固定高度。但是这样做,仍然隐藏了键盘,在屏幕上留下了很多多余的空白space。
因为在这种情况下隐藏键盘是没有用的。我想让它始终可见。
这是集合视图使用固定高度的结果。
直到苹果发布新的 tvOS 14 属性 searchControllerObservedScrollView
:https://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
return 类型更改为 UICollectionViewController
。它应该不会影响您的实施。