简体   繁体   English

如何在集合视图中手动 select 下一个重点索引路径

[英]How to manually select next focused index path in collection view

How can I manually decide the next focused index path for my collection view on tvOS?如何在 tvOS 上为我的集合视图手动决定下一个重点索引路径?

My use case is that I have a collection view with dynamic cells that scrolls in all directions, and sometimes when a cell in one section spans across several cells in the next one, I want to be able to manually decide what cell gets focused next.我的用例是我有一个集合视图,其中包含向各个方向滚动的动态单元格,有时当一个部分中的一个单元格跨越下一个部分中的多个单元格时,我希望能够手动决定接下来关注哪个单元格。

The default behaviour seems to be that the collection view will select the cell in the middle of the previous one.默认行为似乎是集合视图将 select 前一个中间的单元格。

For example, the green cell is currently focused.例如,绿色单元格当前处于焦点位置。 When I navigate down, the collection view wants to focus the red cell, but I want the blue cell to be focused next.当我向下导航时,集合视图想要关注红色单元格,但我希望接下来关注蓝色单元格。

在此处输入图像描述

My initial idea was to implement the collectionView(_:shouldUpdateFocusIn:) delegate function, and return false + trigger a focus update, when the collection view selects the "wrong" index path.我最初的想法是实现collectionView(_:shouldUpdateFocusIn:)委托 function,并在集合视图选择“错误”索引路径时返回false + 触发焦点更新。

However, for some reason, shouldUpdateFocusIn gets called several times when I return false from it and causes a visible lag.但是,由于某种原因,当我从中返回false并导致明显的滞后时, shouldUpdateFocusIn会被调用多次。

func collectionView(_ collectionView: UICollectionView, shouldUpdateFocusIn context: UICollectionViewFocusUpdateContext) -> Bool {
    if let nextIndexPath = shouldFocusCell(context.focusHeading, (context.previouslyFocusedIndexPath, context.nextFocusedIndexPath)) {
        // The collection view did not select the index path of the cell we want to focus next.
        // Save the correct index path and trigger a focus update.
        lastFocusChange = (lastFocusChange.next, nextIndexPath)
        setNeedsFocusUpdate()
        // Using updateFocusIfNeeded() results in the following warning:
        // WARNING: Calling updateFocusIfNeeded while a focus update is in progress. This call will be ignored.
        return false
    }
    return true
}

Next idea was to do the same thing in collectionView(_:didUpdateFocusIn:with:) , but in this case we only update the focus after it has already moved to the "wrong" cell, so it becomes apparent to the user that the focus moves from the wrong cell to the correct one.下一个想法是在collectionView(_:didUpdateFocusIn:with:)中做同样的事情,但在这种情况下,我们只在焦点已经移动到“错误”单元格之后才更新焦点,因此用户可以清楚地看到焦点从错误的单元格移动到正确的单元格。

Not ideal either.也不理想。

I'm using my own subclass of UICollectionViewLayout and UICollectionView , but I don't see anything I can override to be able to manually decide what index path to focus next when navigating up/down/left/right before shouldUpdateFocusIn is called.我正在使用我自己的UICollectionViewLayoutUICollectionView的子类,但我没有看到任何我可以覆盖的内容,以便能够在调用shouldUpdateFocusIn之前手动决定接下来要关注的索引路径。

Is there any way I can achieve this?有什么办法可以做到这一点?

One possibility could be to use collectionView(_ collectionView:, canFocusItemAt:) to let your collectionView know if a given indexPath can receive the focus.一种可能性是使用collectionView(_ collectionView:, canFocusItemAt:)让您的 collectionView 知道给定的 indexPath 是否可以接收焦点。

You can find here below a naive implementation of this concept.您可以在下面找到此概念的简单实现。 You will need to adjust the maths on it to your needs.您将需要根据自己的需要调整其数学。

func collectionView(_ collectionView: UICollectionView, canFocusItemAt indexPath: IndexPath) -> Bool {
    guard let currentlyFocusedCellLayoutAttributes = collectionView.layoutAttributesForItem(at: focusedIndexPath) else { return false }
    guard let cellAtGivenIndexPathLayoutAttributes = collectionView.layoutAttributesForItem(at: indexPath) else { return false }
        
    let currentlyFocusedCellOriginX = currentlyFocusedCellLayoutAttributes.frame.origin.x
    let currentlyFocusedCellOriginY = currentlyFocusedCellLayoutAttributes.frame.origin.y
    let currentlyFocusedCellWidth = currentlyFocusedCellLayoutAttributes.frame.width
        
    let cellAtGivenIndexPathOriginX = cellAtGivenIndexPathLayoutAttributes.frame.origin.x
    let cellAtGivenIndexPathOriginY = cellAtGivenIndexPathLayoutAttributes.frame.origin.y
    let cellAtGivenIndexPathWidth = cellAtGivenIndexPathLayoutAttributes.frame.width
            
    let offsetX = collectionView.contentOffset.x

    // Scrolling horizontally is always allowed
    if currentlyFocusedCellOriginY == cellAtGivenIndexPathOriginY {
        return true
    }
    
    // Scrolling vertically is only allowed to the first cell (blue cell in the screenshot)
    if cellAtGivenIndexPathOriginX <= offsetX {
        return true
    }
    
    return false
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 有没有办法在集合视图中更改焦点索引路径? - Is there a way to change the focused index path in a collection view? 在tvOS中重新加载数据后,集合视图的最后一个聚焦索引路径丢失了 - Collection view's last focused index path lost after reload data in tvOS 如何创建像 AIRBNB 这样的水平集合视图(在幻灯片上自动选择索引路径) - How to create a Horizontal collection view like AIRBNB (Auto select index path on slide) 如何在swift中同时显示表格视图单元格索引路径和集合视图索引路径? - How to show table view cell index path and collection View Index path at the same time in swift? 如何在索引path.item-集合视图中的1中获取单元格 - how to get the cell at index path.item - 1 in collection view 如何从特定索引路径加载集合视图单元格? - How to load collection view cell from a specific index path? 如何快速获取集合视图的当前索引路径 - How to get current index path of collection view in swift 表格视图单元格内的集合视图单元格的索引路径 - Index path of a collection view cell that is inside of a table view cell 如何在使用拖放委托重新排序时知道集合视图单元格的当前索引路径? - How to know the current index path of a collection view cell while reordering using drag and drop delegates? 是否可以在 swift 中显示表格视图单元格索引路径和集合视图索引路径? - Is it possible to show table view cell index path and collection View Index path in swift?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM