2

I am trying to remove line breaks for the items within my section using the UICollectionViewFlowLayout .

At the moment I have

|header         |
|0-0 0-1 0-2 0-3|
|0-4 0-5        |

|header         |
|1-0 1-1 1-2 0-3|
|1-4 1-5        |

and I need :

|header         |
|0-0 0-1 0-2 0-3| 0-4 0-5    

|header         |
|1-0 1-1 1-2 1-3| 1-4 1-5  

so users can horizontally scroll . On iOS i resolve this by creating two nested collectionViews but on tvOS I am unable to replicate the solution because i am unable to focus on the inner cells .

after several tries I override the preferredFocusedView variable on the tableCell where the nested UICollectionView is :

override var preferredFocusedView: UIView? {
  return moviesCollection
}

This behavior allows me to swipe horizontally between the inner elements of the collection but i cannot swipe vertically to change between table cells.

I am kind of lost ,Any kind of help would be greatly appreciated.

Thanks .

cromanelli
  • 576
  • 1
  • 5
  • 21

4 Answers4

1

This can be solved very quickly with a custom UICollectionViewLayout

Subclass UICollectionViewLayout & override the following properties and methods

  1. var collectionViewContentSize: CGSize
  2. func prepare()
  3. func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]?

Make sure to return the correct frame for each cell

Here is my working solution that also conveniently provides some properties of UICollectionViewFlowLayout (itemSize, minimumInteritemSpacing, minimumLineSpacing).

You might not need to change anything and just add it to your project.

https://gist.github.com/kflip/52ec15ddb07aa830d583856909fbefd4

Feel free to add scrollDirection support ... its scrolling in both directions already, but you might want to change if one section should be displayed as column instead of a row...

You could also add FlowLayout-like protocol functionalities if you need more customisations based on IndexPaths (e.g. CellSize)

  • I think this is the way you should go. Here's an official guide of using custom UICollectionViewLayout [https://developer.apple.com/library/content/documentation/WindowsViews/Conceptual/CollectionViewPGforIOS/CreatingCustomLayouts/CreatingCustomLayouts.html] – Ryan Nov 30 '16 at 19:21
1

Updated

Here's a GIF showing the end result: enter image description here

Original

I've just created a test ViewController and this seems to work alright. Basically, what I have there is a UICollectionView with a vertical flow layout. Each cell of that collectionView has it's own UICollectionView set with an horizontal flow layout.

The only incovenient for the "out of the behavior" is that the horizontal flow layour collection view does not "remember" the selected item when coming back to it but that can be solved with a little bit of playing around.

Hope it helps. Here's my code for it:

class ViewController: UIViewController, UICollectionViewDataSource {

    @IBOutlet weak var collectionView: UICollectionView!

    override var preferredFocusEnvironments: [UIFocusEnvironment] {
        return [collectionView]
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    // MARK: - UICollectionViewDataSource

    func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 3
    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 1
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        return collectionView.dequeueReusableCell(withReuseIdentifier: "ParentTestCell", for: indexPath)
    }

    func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
        return collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "TestHeader", for: indexPath)
    }

}

// Parent cell - included in the vertical collection view & includes the horizontal collection view

class ParentTestCell: UICollectionViewCell, UICollectionViewDataSource {

    @IBOutlet weak var collectionView: UICollectionView!

    override var preferredFocusEnvironments: [UIFocusEnvironment] {
        return [collectionView]
    }

    // MARK: - UICollectionViewDataSource

    func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 1
    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 10
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        return collectionView.dequeueReusableCell(withReuseIdentifier: "TestCell", for: indexPath)
    }

}

// Child cell - included in the horizontal collection view

class TestCell: UICollectionViewCell {

    override func didUpdateFocus(in context: UIFocusUpdateContext, with coordinator: UIFocusAnimationCoordinator) {
        coordinator.addCoordinatedAnimations({ 
            if self.isFocused {
                self.backgroundColor = .red
            }
            else {
                self.backgroundColor = .blue
            }
        }, completion: nil)
    }

}

And here's the storyboard structre:

enter image description here

Mihai Fratu
  • 7,579
  • 2
  • 37
  • 63
0

Just a suggestion if it can help you.

  1. Add tableView
  2. Create Custom TableVeiwCell which contains collection view inside the cell with horizontal scrolling.
  3. for each section you have, will become number rows for tableview
  4. for items in row becomes number of items for the respective collection view.
Ravi Kiran
  • 185
  • 1
  • 10
-1

A UICollectionView lay out its cells in a very specific way when using UICollectionViewFlowLayout, I'm not sure it's possible to make that kind of behaviour with a collectionview, whitout making your own UICollectionViewLayout. See this guide on how to make a UIColloctionView with a custom layout.

I would suggest trying to solve the problem, by using nested UITableViews. Make a vertical scrolling tableview, where every cell in the tableview has it's own horizontal scrolling tableview. The cells in the horizontal tableview, will be the actual cells that the user can select. See this guide on how to do this.

This should work in tvOS as well, since the focus engine should look through the cells subviews, and find the focusable ones. I hope it helps :)

Community
  • 1
  • 1
Wiingaard
  • 4,150
  • 4
  • 35
  • 67
  • that is the approach i did for the iOS version of the app . On the tvOS version it does not work since the table's cell gets the focus and then you cannot select the inner collection or tables. – cromanelli Nov 26 '16 at 15:55