Create Streaming app Home Screen on tvOS
(Part 5 of 8)
This is the fifth part of our tvOS Bootcamp. Please check out the previous pages to know more about this series.
In this tutorial, we are going to create several view components to render a list of Movies or Series in our app.
This is how the Home screen is supposed to look as per our mocks:
Since our HomeViewController
is common for both, we will differentiate the type of data using a property of type HomeScreenType
enum, it can either be .movies
or .series
.
As the UI shows, we need to integrate various carousels, each having a title and a horizontally scrollable list of data (assets).
The approach we would take to create this is by using a parent UICollectionView
which will contain a list of carousels.
Each carousel would be in fact a part of another UICollectionView
which would be rendered inside a UICollectionViewCell
with scrollDirection set to horizontal.
In our app, RailCell
is a cell which contains a horizontal collection view having a list of AssetCell
objects, each representing a Movie or Series.
Firstly, we will create the parent UICollectionView
in our XIB and create its outlet in our class. We will then setup this collection view in a method called setupView()
Here we setting the datasource & delegates of this collectionView.
We will also register the carousel cells named RailCell
and section header view called RailHeaderView
. This view contains a title to be shown on top of each carousel/rail.
Next step is to implement the UICollectionViewDataSource
& UICollectionViewDelegateFlowLayout
.
UICollectionVieDataSource
is implemented like this:
Number of sections would be equal to the number of carousels we need to show. Thus, we are returning data array count from PageModel
. We will shortly see how to fetch this page using NetworkManager
.
Number of items in each section are restricted to 1. That is because we need to show only a single cell in each section. This cell will in-turn show a horizontal list of data.
In third method, we are simply creating an instance of RailCell
using standard format and loading its data using loadData
method.
We are also using a closure to know when a cell inside the nested collection view is tapped in order to open the Detail scree using openDetails
method.
Last method of this delegate returns an instance of RailHeaderView
, used to show the header on top of the carousel.
To mention the sizes of each carousel cell & header, we need to implement UICollectionViewDelegateFlowLayout
Here we are simply returning the desired size of the carousel cells based on the screen type. Please note that we have also created a class named Constants
to hold all our static data to make them dynamic.
Second method returns the size of the header.
Now that we have linked our UI, let’s go ahead and fetch data for Movies or Series like this:
This method uses type enum to identify what kind of data is required for Home screen. Based on that, appropriate method from NetworkManager
is used to fetch data.
Please note that both of these methods return a same type of data with the only difference at the view level. Movies cells are shown in Portrait mode whereas Series cells are shown in Landscape mode.
This is how the loadData
method looks like:
Before seeing the data, we need to discuss how nested UICollectionView
is created inside RailCell
.
Firstly, we will create a file named RailCell
, it will be of UICollectionVieCell
type. We then need to integrate a UICollectionView inside the XIB and create an outlet in respective swift file.
This is how the file looks like:
Starting from the beginning, this class contains a property RailModel
which is provided externally using loadData
method.
UICollectionView
is being setup the same way like we did in HomeViewController
above.
This is how the datasource and delegates look like:
There are many important things to note here in order to achieve the correct Focus behaviour in carousels.
We need to set the canBecomeFocused
property of the carousel cells RailCell
false
. On the contrary, we need to set focus for each asset true
using collectionview delegate method. This will ensure that carousel cells are not stealing focus from the child cells.
Data in each asset is loaded by using a method loadData
in AssetCell
. Let’s take a look at its implementation.
AssetCell
is simply a blank UICollectionViewCell
. We are making use of system provided UI using TVUIKit. This framework provided by Apple and it contains a few boilerplate views which could be used in tvOS apps.
For example TVPosterView
in our project is used inside AssetCell
to show an image and a title. One important advantage of using system defined UI is that it guarantees to appear great in all sizes. It also has the focus animation in its imageview and the title has a slight “Marque” effect when a user rests on a specific cell for a few seconds. Developing all of these require additional effort hence are avoided from the initial implementation of this bootcamp.
Now we will just run the app and our beautiful UI would be rendered.
Our next task is to make all of these clickable by implementing a Detail screen.
https://atulkhatri.medium.com/create-movie-series-detail-screen-on-tvos-84bf4c8c393a