In this tutorial, you’ll learn how to create a horizontal scroll that snaps into place by recreating parts of the Games section in the App Store.
🔻 Download the Judo file.
To make it easy to follow along, download this starter file: Starter File.judo
What’s in the starter file
In this starter file, you’ll find a Component called Game Item that’s complete with several Text layers and an Image that’s formatted in a 16:9 ratio. There’s also a screen Component called Main, which is where we’re going to be building the horizontal scroll that snaps into place.
Create a horizontal Scroll View
To start building a horizontal scroll that snaps into place, we’ll begin by inserting 5 Instances of the Game Item Component. You can do so by either:
Heading to the Insert (+) menu to insert the Game Item Component Instance.
Right-clicking the Component in the Layers panel or canvas to copy, and then right-clicking again to paste in the Instance.
Selecting the Component in the Layers panel or canvas, and then using the keyboard shortcuts ⌘C to copy it and ⌘V to paste in an Instance.
Right-clicking on the Component in the Layers panel or on the canvas to duplicate it.
Then, select all of the Component Instances to embed them into an HStack to organize them horizontally. There are a number of ways to do that as well, but let’s simply click on the HStack toolbar button.
Right now, all of the Component Instances are squished together to fit the screen, so let’s wrap them in a Scroll View container, and from the Inspector panel, we’ll change the Axis to Horizontal and remove the scroll bar indicator.
📱 Preview the design on your mobile device.
Send the file over to your phone to preview it using the Judo mobile app. You should be able to horizontally scroll through the Game Item Component Instances.
Using the Container Relative Frame modifier
Now let’s update the frames of each Component Instance. To do so, select all Game Item Instances from the Layers panel and apply the Container Relative Frame modifier to all of them.
This modifier is useful for creating invisible frames that have a size relative to the nearest container. You can configure the Alignment and Spacing of the container as well as the:
Axis, which determines whether a layer’s width, height, or both will be used for setting the size of the container.
Count, which refers to the total number of rows or columns that the container should be divided into.
Span, which refers to the number of rows or columns that each layer should occupy.
For instance, if we set the Count to 3 and the Span to 1, each layer is going to take up one-third of the screen horizontally. If we change the Span to 2, then each layer will take up two-thirds of the screen instead.
⬇ Note
The spacing you see between each Game Item Instance comes from the HStack that all of the layers are wrapped in, which is set to the default of 8 points.
For this example, let’s set the Count to 10 and the Span to 9.
To give our container some breathing room, let’s also apply some Padding to the HStack that contains all of our Game Item Instances.
📱 Preview the design on your mobile device.
Now when we send this file over to the Judo mobile app, we can fully see the first Game Item and a sliver of the second game, nudging the user that they can scroll horizontally to see more.
Using the Scroll Target Behavior modifier
Let’s apply the Scroll Target Behavior modifier to our horizontal Scroll View container to make the scroll snap. We can either set it to:
Paging, which moves layers within a Scroll View by exactly one screen width or height, depending on the direction.
View Aligned, which allows the Scroll View to snap between child layers.
Let’s set it to View Aligned.
Using the Scroll Target Layout modifier
To make the scroll snap in place for each game that’s featured, we’ll need to apply the Scroll Target Layout modifier to the HStack that contains all of the Game Item Instances. By setting the Is Enabled parameter to True, every layer will become a scroll target. Therefore, the Scroll View container will align with its children layers like so.
Configure the Game Item Instances
Awesome, all that’s left now is to configure the Properties of each Game Item Instance in the Inspector panel. The starter file already comes with a few images, but feel free to add your own.
📱 Preview your final design on the Judo mobile app.
When you’re done, send the file over to your mobile device to preview your final design.
Check out the Code Inspector
As we were designing, Judo was generating SwiftUI in real time, so let’s take a quick peek at the Code Inspector.
struct Main: View {
var body: some View {
ZStack {
NavigationStack {
ScrollView(.vertical, showsIndicators: true) {
VStack {
ScrollView(.horizontal, showsIndicators: false) {
HStack {
Game_Item(now: "HAPPENING NOW", title: "Call of Duty: Mobile", description: "Celebrate four years of combat", image: Image("Cover Image COD Mobile"))
.containerRelativeFrame(
.horizontal,
count: 10,
span: 9,
spacing: 0,
alignment: .center
)
// Repeats for each game
}
.padding()
.scrollTargetLayout(isEnabled: true)
}
.scrollTargetBehavior(.viewAligned(limitBehavior: .automatic))
}
}
.navigationTitle("Games")
}
}
}
}
You’ll find the ScrollView()
container that we had added in, which we had set to .horizontal
and where we hid the scroll bar indicator (showsIndicators: false
).
You’ll also find each Game_Item()
Component Instance that we had added, complete with the .containerRelativeFrame()
modifier and configured the same way we had: with a count
set to 10
and the span
set to 9
.
After the closing bracket of the HStack{}
, you’ll find the .scrollTargetLayout(isEnabled: true)
modifier that we had applied and the .scrollTargetBehavior()
modifier that had had applied to the ScrollView()
container and set to .viewAligned()
.
Resources
🔻 Download the Judo file.
Get your hands on the final App Store file: App Store.judo