Focus engine behaviour for UICollectionView

I use a standard

UICollectionView
with sections. My cells are laid out like a grid. The next cell in a chosen direction is correctly focused if the user moves the focus around with the Apple TV remote. But if there is a "gap" in the grid, the default focus engine jumps over sections. It does this to focus a cell which could be several sections away but is in the same column.


Example: There are 3 sections. The first section has 3 cells. The second has 2 cells and the last one has 3 cells again. See the following image:

http://i.stack.imgur.com/ums8b.png


If the green cell is focused and the user touches the down direction, the yellow cell gets focused and section two is skipped by the focus engine.

I would like to force it that no sections can get jumped over. So instead of focusing the yellow cell I would like to focus the blue cell.


I looked into the delegate methods in

UICollectionViewDelegate
like
shouldUpdateFocusInContext:
which informs the delegate about the focus update. But that delegate method only allows to disable the focus update and not change it to an other cell. I also played around with
canFocusItemAtIndexPath:
but was not able to achieve the desired behaviour.


There seems to be no other delegate method which could do that. Is there an other way?

Answered by Frameworks Engineer in 95570022

There is no direct hook into UICollectionView for accomplishing this, so you'll have to manage the layout yourself. You could add the focus guide on top of cells or supplementary/decoration views to piggyback on the collection view's layout system, or you could add the focus guide to the collection view itself and update its layout whenever the collection view finishes layout, based on the new position of the cells.


Also, we would definitely be interested in any suggestions you may for improving the SDK. Feel free to file feature requests at bugreporter.apple.com.

You are correct that you cannot achieve this behavior using only `UICollectionViewDelegate` methods. However, there are some other approaches you can try.


First, by using focus guides. The `UIFocusGuide` class allows you to create invisible, focusable regions onscreen that redirect to other focusable views when focused. You could cover your entire section in a focus guide, or just the empty spaces, and have them redirect to the correct cell.


Second, by composing collection views. Your screenshot shows a similar UI to the built-in iTunes Movies and TV Shows apps, where content is arranged in horizontally-scrolling "shelves" composed in a vertically scrolling UI. You can accomplish something similar by having an outer vertical collection view with one cell per "shelf", where each shelf cell contains another horizontal collection view with the shelf's contents. `UICollectionView` automatically implements the behavior you want, where moving focus into an empty space in a collection view will redirect to the nearest cell. So, if each row has its own collection view, then you'll get the desired behavior.


As always, please file an feature request at bugreporter.apple.com if there is specific functionality you would like to see added in the future.

Thanks for this wonderful answer, but how would you cover an entire section or the empty space with a focus guide? Should I add FocusGuides as invisible cells? Is there some other hook into UICollectionView. I could try to misuse decoration views for this but that somehow feels wrong.

Accepted Answer

There is no direct hook into UICollectionView for accomplishing this, so you'll have to manage the layout yourself. You could add the focus guide on top of cells or supplementary/decoration views to piggyback on the collection view's layout system, or you could add the focus guide to the collection view itself and update its layout whenever the collection view finishes layout, based on the new position of the cells.


Also, we would definitely be interested in any suggestions you may for improving the SDK. Feel free to file feature requests at bugreporter.apple.com.

Focus engine behaviour for UICollectionView
 
 
Q