Instagram Story Carousel in SwiftUI

simon mcneil
4 min readJan 14, 2023

--

Hello hello, and welcome to my first story of 2023! In this story you will learn how to create the Instagram story carousel in SwiftUI:

To get started, create a new xCode project and select SwiftUI. If you want access to the same files that I used, then you can grab them in the repo: https://github.com/SimonSays1993/Instagram---Top-Scroll-View-Stories/tree/main/Instagram. If you want to use your own images, then just drag and drop them into your assets folder.

Lets begin by creating the circle view. Create a new file and called it ProfileView. To replicate the one that Instagram has we need to add a circular profile image with a bordered circular gradient around it. We also want this view to be re-usable with different profiles, so we’ll give it two variables at the top. Lets call these image and name. Add the following to your ProfileView view:

struct ProfileView: View {
var image: String
var name: String

var body: some View {
VStack {
Image(image)
.resizable()
.frame(width: 60, height: 60)
.cornerRadius(50)
}
}
}

struct ProfileView_Previews: PreviewProvider {
static var previews: some View {
ProfileView(image: "profile", name: "Simon McNeil")
}
}

This will give us a simple small circular profile. To add the gradient bordered background we will use the overlay modifier with the circle shape. The circle shape will use the stroke and frame modifier. Update your Image view like so:

    var body: some View {
VStack {
Image(image)
.resizable()
.frame(width: 60, height: 60)
.cornerRadius(50)
}
.overlay(
Circle()
.stroke(LinearGradient(colors: [.red, .purple, .red, .orange, .yellow, .orange],
startPoint: .topLeading,
endPoint: .bottomTrailing), lineWidth: 2.3)
.frame(width: 68, height: 68)
)
}

Its amazing how easy it is to add gradients with SwiftUI to your shapes :)

Lastly we just need to add the label below the image. Embed your current VStack in another VStack and put a Text label at the bottom of it:

    var body: some View {
VStack {
VStack {
Image(image)
.resizable()
.frame(width: 60, height: 60)
.cornerRadius(50)
}
.overlay(
Circle()
.stroke(LinearGradient(colors: [.red, .purple, .red, .orange, .yellow, .orange],
startPoint: .topLeading,
endPoint: .bottomTrailing), lineWidth: 2.3)
.frame(width: 68, height: 68)
)
.frame(width: 70, height: 70)

Text(name)
.font(.caption)
}
}

Noticed we also added a new frame of .frame(width: 70, height: 70). This is so the top of the circle will not be cut off in the safe area of the device. You’ll see this come into play when we incorporate it in the home view.

Your ProfileView view should look like the following:

Lets create another SwiftUI view file and call this one StoryCarousel. To put the ProfileView profile views in a carousel we need to use a ScrollView with a direction of horizonal. Then inside the ScrollView we will put the profile images inside an HStack:

Your file should look like the following:


struct StoryCarousel: View {
var body: some View {
ScrollView(.horizontal, showsIndicators: false) {
HStack(spacing: 15) {
ProfileView(image: "profile", name: "Simon McNeil")
ProfileView(image: "profile1", name: "Sophie T")
ProfileView(image: "profile2", name: "James")
ProfileView(image: "profile3", name: "Sam")
ProfileView(image: "profile4", name: "Darren")
ProfileView(image: "profile5", name: "Dara")
ProfileView(image: "profile6", name: "Katie")
ProfileView(image: "profile7", name: "Pom")
ProfileView(image: "profile", name: "Simon McNeil")
}
.padding(.horizontal, 8)
}
.padding(.vertical, 10)
}
}

struct StoryCarousel_Previews: PreviewProvider {
static var previews: some View {
StoryCarousel()
}
}

Now your canvas should be looking similar to this, with the functionality of being able to scroll horizontally:

To put it all together lets now go back to the ContentView and put the StoryCarousel we just created in a VStack. Also in the VStack lets add a Spacer() below it to position it at the top of the screen.

struct ContentView: View {
var body: some View {
// This VStack will act as the main container
VStack(spacing: 0.0) {

StoryCarousel()

Spacer()

}
}
}

If you recall I mentioned we added .frame(width: 70, height: 70) in the ProfileView. If you want to better understand why we added this, then comment it out and come back and look at the preview in ContentView. You will see the top of the circle is being cut off.

Well that's it! You now have a fully functional horizontal carousel that has the same UI/UX as Instagram

BONUS

If you want to give it the same nav bar that Instagram has then create a new SwiftUI file with the following inside of it:

struct Header: View {
var body: some View {
HStack {
Image("logo")

Spacer()

HStack(spacing: 20.0) {
Image("add")
Image("heart")
Image("messenger")
}
}
.padding(.horizontal, 15)
.padding(.vertical, 3)
}
}

Then add the header above StoryCarousel in your ContentView

struct ContentView: View {
var body: some View {
// This VStack will act as the main container
VStack(spacing: 0.0) {
Header()
StoryCarousel()
Spacer()
}
}
}

Your view should now look like the following:

Thanks :)
Source Code: https://github.com/SimonSays1993/Instagram---Top-Scroll-View-Stories

--

--