我需要指定哪个细胞应该获得焦点。
根据Apple文档,如果indexPathForPreferredFocusedView
属性为remembersLastFocusedIndexPath
,或者如果没有保存的索引路径,则应调用false
委托方法,因为之前没有关注任何单元格。
在我的情况下,我在UIViewController
中使用了一个集合视图,并将remembersLastFocusedIndexPath
设置为false
,但未调用indexPathForPreferredFocusedView
。
如何解释这种行为?
答案 0 :(得分:5)
The function indexPathForPreferredFocusedView
is part of UICollectionViewDelegate, so it might be that the delegate was not assigned to your collectionView.
Or, the problem might also be on the focus environment, not taking into account your UICollectionView.
As a reference, here you have an example of a simple collectionView with 5 cells, having the one in the center initially selected by default
import UIKit
class ViewController: UIViewController {
private var collectionView: UICollectionView!
private var items = ["One", "Two", "Three", "Four", "Five"]
override var preferredFocusEnvironments: [UIFocusEnvironment] {
return [collectionView]
}
override func viewDidLoad() {
super.viewDidLoad()
collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: UICollectionViewFlowLayout())
collectionView.remembersLastFocusedIndexPath = false
MyCell.register(in: collectionView)
view.addSubview(collectionView)
collectionView.dataSource = self
collectionView.delegate = self
}
}
extension ViewController: 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
}
}
extension ViewController: UICollectionViewDelegate {
func indexPathForPreferredFocusedView(in collectionView: UICollectionView) -> IndexPath? {
return IndexPath(row: 2, section: 0)
}
}
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)
}
}
答案 1 :(得分:2)
Swift 4: 我遇到了同样的问题。我想重新加载collectionview
并将焦点集中在特定的单元格上。如果设置了collectionView.remembersLastFocusedIndexPath = true
,则会调用indexPathForPreferredFocusedView
委托方法。但它会记住属性名称中所说的最后一个聚焦indexPath。这不是我想要的。苹果文档令人困惑。
尝试一下:
实现委托方法:
func indexPathForPreferredFocusedView(in collectionView: UICollectionView) -> IndexPath? {
return IndexPath(item: 5, section: 0)
}
强制更新焦点[例如:通过按钮操作]:
collectionView.setNeedsFocusUpdate()
collectionView.updateFocusIfNeeded()
这将强制collectionView调用indexPathForPreferredFocusedView
方法。我们不必将remembersLastFocusedIndexPath
设置为true。
注意:我的屏幕上有多个collectionViews,并且执行了上述步骤 仅在当前关注的collectionView和 我们强迫焦点更新的collectionView是相同的。
使用preferredFocusEnvironments
返回首选集合视图,使其在加载视图时成为焦点(例如)。
override var preferredFocusEnvironments: [UIFocusEnvironment] {
return [collectionView2]
}
答案 2 :(得分:1)
您应将remembersLastFocusedIndexPath
设置为true
。
collectionView.remembersLastFocusedIndexPath = true
答案 3 :(得分:0)
根据我的尝试,仅在indexPathForPreferredFocusedView
设置为true时才调用collectionView.remembersLastFocusedIndexPath
。
此外,当再次重新加载collectionView
以获取首选的Focus时。
使用preferredFocusEnvironments
也是一个很好的解决方案,但是它有其缺点。
如果您的ViewController
只有collectionView
,那么使用它是很好的。如果ViewController
中有多个焦点项目,则焦点行为将有所不同。
答案 4 :(得分:0)
三件事解决了我面临的相同问题。
self.restoreFocusAfterTransition = false
func indexPathForPreferredFocusedView(in collectionView: UICollectionView) ->
IndexPath? {
return IndexPath(item: 3, section: 0)
}
override var preferredFocusEnvironments : [UIFocusEnvironment] {
//return collectionView in order for indexPathForPreferredFocusedView method to be called.
return [collectionView]
}
我在两个不同的视图控制器中有两个集合视图。我将UICollectionView子类化,并正在执行从一个视图控制器到另一个视图控制器的转换。
答案 5 :(得分:0)
我也遇到了这个问题。
要修复它:
collectionView.remembersLastFocusedIndexPath = true
在reloadData()
之后:
collectionView.setNeedsFocusUpdate()
collectionView.updateFocusIfNeeded()
迫使它集中在最后一个集中的项目上。