Custom Image Slider View in SwiftUI

903 Views Asked by At

I have recently been using PageTabViewStyle() on the tabViewStyle modifier of the TabView. However I wanted a more custom design, like the image below, but i do not know how to do it.

What i want is essentially sliding views (i will replace those gray views with movie posters), the middle view which is selected should be the largest, while others next to it to be smaller, i want to be able to slide the views horizontally. How can this be achieve this design?

Image Slider

1

There are 1 best solutions below

0
berkaneks On

If I were you, I would use LazyHStack inside the ScrollView and then use GeometryReader to determine the position of the items in LazyHStack. And finally use scaleEffect modifier. Something like this:

var body: some View {
    ScrollView(.horizontal, showsIndicators: false) {
        LazyHStack(spacing: 20) {
            ForEach(0..<moviePosters.count, id: \.self) { index in
                GeometryReader { geometry in
                    let scale = getScale(for: index)
                    let isSelected = index == selectedTabIndex

                    MoviePosterView(imageName: moviePosters[index], isSelected: isSelected)
                        .frame(width: 150, height: 200)
                        .scaleEffect(isSelected ? scale : 1.0)
                        .onTapGesture {
                            selectedTabIndex = index
                        }
                        .offset(x: 0, y: isSelected ? -20 : 0)
                }
                .frame(width: 150, height: 200)
            }
        }
        .padding(.horizontal, 20)
    }
    .frame(height: 220)
}

// Calculate the scale factor based on the distance from the center item
func getScale(for index: Int) -> CGFloat {
    let selectedIndex = CGFloat(selectedTabIndex)
    let distance = abs(selectedIndex - CGFloat(index))
    return max(1.0 - (distance * 0.2), 0.8) // Adjust the scaling factor as needed
}

let moviePosters = ["poster1", "poster2", "poster3", "poster4"] // Replace with your movie poster image names

And then also create MoviePosterView like:

struct MoviePosterView: View {
var imageName: String
var isSelected: Bool

var body: some View {
    Image(imageName)
        .resizable()
        .aspectRatio(contentMode: .fill)
        .clipShape(RoundedRectangle(cornerRadius: 10))
        .overlay(
            RoundedRectangle(cornerRadius: 10)
                .stroke(Color.white, lineWidth: isSelected ? 2 : 0)
        )
}