Exploring MusicKit and Apple Music API
Unlock the full power of MusicKit & Apple Music APIs in your apps with the best guide! Use code musickit-blog for a limited-time 35% discount!
In iOS 14, SwiftUI introduced the PageTabViewStyle
for implementing a paged scrolling TabView. This helps you easily create a carousel-like view that you can use in the onboarding or the header view similar to what we have in the App Store app.
For tvOS, after some experimentation, I realized that the .page
does give you the page control but does not provide with those extra little sides of the secondary views. Those usually provide the experience that there are other scrollable views on the left and the right. So, if you want to hide the page control, how do you know it is horizontally scrollable?
You use the ScrollView with the axis as horizontal
.
This post explores both the methods of creating a carousel view.
TabView and PageTabViewStyle
You can put your list of views inside a TabView
and add the tab view style as page. It automatically provides you with a carousel view with an embedded page control.
struct HomeView: View {
@StateObject private var viewModel = QuotesViewModel()
var body: some View {
GeometryReader { geometry in
let height = geometry.size.height
if !viewModel.quotesList.isEmpty {
TabView {
ForEach(viewModel.quotesList) { quote in
QuoteCarouselView(quote: quote)
.focusable()
}
}
.tabViewStyle(.page)
.frame(maxHeight: height * 0.65)
}
}
}
}
One thing to note is that the TabView
does not seem to work lazily and loads all the views at once. So, you are fine with TabView
if there are a few views inside it.
Otherwise, if you want to create an infinite carousel, let’s look at another alternative.
ScrollView and LazyHGrid
You can use the ScrollView
with LazyHGrid
to get the little side views without the page control. This option is given in the session Build SwiftUI Apps for tvOS. Although, in the example given, you have to figure out the frame on your own.
Using some tiny magic of GeometryReader
, you can provide the maximum height to the whole scroll view and maximize the width of each carousel view displayed on the screen.
Providing a width is necessary because the default is infinite in a horizontal scroll view without the width.
struct HomeView: View {
@StateObject private var viewModel = QuotesViewModel()
var body: some View {
GeometryReader { geometry in
let height = geometry.size.height
let width = geometry.size.width
ScrollView(.horizontal) {
LazyHGrid(rows: [.init()]) {
ForEach(viewModel.quotesList) { quote in
QuoteCarouselView(quote: quote)
.focusable()
.frame(width: width)
}
}
}
.frame(maxHeight: height * 0.65)
}
}
}
Running the app, we get the following beautiful carousel view:
Conclusion
While the initial impressions with SwiftUI’s support for tvOS haven’t been great, I am still looking forward to experimenting on the large screen.
Tag @rudrankriyam on Twitter if you have experience working with tvOS and want to spread some knowledge around!
Thanks for reading, and I hope you’re enjoying it!
Exploring MusicKit and Apple Music API
Unlock the full power of MusicKit & Apple Music APIs in your apps with the best guide! Use code musickit-blog for a limited-time 35% discount!