UICollectionView relative focus

Hello,


I was wondering if anyone could give some tips on how to achieve this:

I have a tableview with a number of cells.

Each UITableCiewCell subclass has a UICollectionView with horizontal flowlayout (and scroll)


If the focus is on the 3rd cell of of the 1st UICollectionView (1st UITableCiewCell), swiping down to another UITableCiewCell should keep you at the same UICollectionView column. Instead the focus jumps to the first cell of the UICollectionView.

Are there any properties I can use to achieve the expected behavior?


Thank you in advance for your help!

Answered by Frameworks Engineer in 205776022

Hello,


You should definitely be able to achieve what you want. Some questions to help me diagnose what the issue is:

  • Are the table view cells, which contain the collection views, focusable themselves? Or have you configured them to not be focusable? (It's possible that, depending on how you have if configured, swiping down is actually focusing the table view cell first, which is then redirecting focus to the collection views inside. If so, we'll need to change this.)
  • Are the collection view's configured to have `remembersLastFocusedIndexPath` set to `YES/true`? We'll want this set to `NO/false`, which is the default, to ensure that focus moves geometrically.


A helpful technique for seeing what the focus engine is thinking during a focus update is to look at `UIFocusUpdateContext` Quick Look images. To see this, set a breakpoint in a `-didUpdateFocusInContext:withAnimationCoordinator:` method for the table view, or a view or view controller that contains the table view. Now run your app and swipe down to move between table view rows, which should trigger the breakpoint. In Xcode's debugger, find the variable representing the `context` (of type `UIFocusUpdateContext`) that is passed in as an argument to that method. Now select it, and click the Quick Look icon or press the space bar to activate Quick Look. This should show an image of the focus update from the perspective of the focus engine. If you are able, reply to this thread with that image attached and I can explain what's going on.

Accepted Answer

Hello,


You should definitely be able to achieve what you want. Some questions to help me diagnose what the issue is:

  • Are the table view cells, which contain the collection views, focusable themselves? Or have you configured them to not be focusable? (It's possible that, depending on how you have if configured, swiping down is actually focusing the table view cell first, which is then redirecting focus to the collection views inside. If so, we'll need to change this.)
  • Are the collection view's configured to have `remembersLastFocusedIndexPath` set to `YES/true`? We'll want this set to `NO/false`, which is the default, to ensure that focus moves geometrically.


A helpful technique for seeing what the focus engine is thinking during a focus update is to look at `UIFocusUpdateContext` Quick Look images. To see this, set a breakpoint in a `-didUpdateFocusInContext:withAnimationCoordinator:` method for the table view, or a view or view controller that contains the table view. Now run your app and swipe down to move between table view rows, which should trigger the breakpoint. In Xcode's debugger, find the variable representing the `context` (of type `UIFocusUpdateContext`) that is passed in as an argument to that method. Now select it, and click the Quick Look icon or press the space bar to activate Quick Look. This should show an image of the focus update from the perspective of the focus engine. If you are able, reply to this thread with that image attached and I can explain what's going on.

Thank you Matt.

I followed your recommendation by putting the table view cells as non focusable and configured the collection view's to to have `remembersLastFocusedIndexPath` set to `false` and was able to move the focus geometrically.


When pressing the collection vie cell, I do show a details page. Im my application I do need to focus the originally pressed cell when the user goes back to the main view.


I'm trying to replcate the behavior to remember the last focus indexPath and focus the related cell

I tried to save the indexPath manually but could not see how to force the focus engine to it


My code:


func collectionView(_ collectionView: UICollectionView, shouldUpdateFocusIn context: UICollectionViewFocusUpdateContext) -> Bool {

guard let to = context.nextFocusedIndexPath else {

return true

}

guard context.previouslyFocusedIndexPath != nil else {

return true

}

currentlyFocusedItem = (to as NSIndexPath).item

manualFocusCell = IndexPath(item: currentlyFocusedItem, section: 0) as NSIndexPath?

return true

}

func indexPathForPreferredFocusedView(in collectionView: UICollectionView) -> IndexPath? {

return manualFocusCell as IndexPath?

}

For this new problem, can you be specific about what behavior you are seeing without the patch above?

Without the patch the when going back from details view to the main view with the tableview the focus is always set to the first UICollectioViewCell (index 0)


Scenario:

1- Navigate to the 3rd cell of the collection view and select

2- Here I do display a details page for the selected cell

3- From Siri remote I press back to the main view

RESULT: The focus is set to the 1st cell of the collection view. I was expecting the focus to be set the 3rd cell.


Having remembersLastFocusedIndexPath set to true for the collection view fixes the issue but I lose the geometrically focus.

Thank you again for your help!

If you want to save the last focused item/inde path, save it in `-collectionView:didUpdateFocusInContext:withAnimationCoordinator:` as opposed to `shouldUpdateFocusInContext...`


Also, to ensure that the focus system uses your manual preferences to restore focus when dismissing the presented/pushed details pages, set `restoreFocusAfterTransition` on the presenting view controller to false.


Finally, please file a radar at http://bugreporter.apple.com with a sample project attached. A sample project will allow us to provide more specific advice for your needs, and also help us to try to improve these kinds of situations in the future.

UICollectionView relative focus
 
 
Q