Carousel Flicker

Hi, I've created an carousel using an Tabview component and it is divided in pages, each page has 7 items. Now we wan't to load the carousel page by page, but whenever I updated the list which Tabview uses to render, it flickers because it rerenders previous elements.

I've tried to use a scroll view for this but this app is for Vision Pro and I added some 3D transformations (position/rotation) to the cards from the tabview and when I added this in the scrollview they becom unclickable.

Do you have any sugestions what can I do?

Bellow is a sample of the code, I put [items] just to suggest there is a list.

VStack (spacing: 45) {
            TabView(selection: $navigationModel.carouselSelectedPage) {
                let orderedArtist = [items]
                let numberOfPages = Int((Double(orderedArtist.count) / Double(cardsPerPage)).rounded(.up))
                
                if(numberOfPages != 1){
                    Spacer().tag(-1)
                }
                
                ForEach(0..<numberOfPages, id: \.self) { page in
                    LazyHStack(alignment: .top, spacing: 16){
                        ForEach(0..<cardsPerPage, id: \.self) { index in
                            if(page * cardsPerPage + index < orderedArtist.count){
                                let item = orderedArtist[page * cardsPerPage + index]
                                GeometryReader{proxy in

Hi @AndreiAvram99 ,

Try out this code to create a carousel and let me know if that helps:


struct Carousel: View {
    
    @State private var items: [Item] = []
    
    @State private var scrollID: Int?
    
    /// The number of items that can be visible (while not actively scrolling)
    let visibleItemCount: Int
    
    /// The space between items.
    let spacing: CGFloat
    
    private let frontPaddingItems: [PaddingItem]
    private let backPaddingItems: [PaddingItem]
    
    init(visibleItemCount: Int, spacing: CGFloat) {
        
        self.visibleItemCount = visibleItemCount
        self.spacing = spacing
        
        let paddingCount = visibleItemCount / 2
        
        frontPaddingItems = (0..<paddingCount).map({ _ in
            .init()
        })
        
        backPaddingItems = (0..<paddingCount).map({ _ in
            .init()
        })
    }
        
    var body: some View {
        VStack {
            ScrollView(.horizontal) {
                LazyHGrid(rows: [.init(.flexible())], spacing: spacing) {
                    
                    // Pad the front.
                    ForEach(frontPaddingItems) { item in
                        item.color
                            .containerRelativeFrame(.horizontal, count: visibleItemCount, spacing: spacing)
                    }
                    
                    
                    ForEach(items) { item in
                        item.color
                            .containerRelativeFrame(.horizontal, count: visibleItemCount, spacing: spacing)
                            .clipShape(.rect(cornerRadius: 40))
                            .overlay {
                                Text(item.id.description)
                            }
                            .scrollTransition { content, phase in
                                content
                                #if os(visionOS)
                                    .offset(z: phase.isIdentity ? 300 : 0)
                                #else
                                    .scaleEffect(x: phase.isIdentity ? 1.0 : 0.80,
                                                 y: phase.isIdentity ? 1.0 : 0.80)
                                #endif
                                    
                            }
                    }
                    // Pad the back.
                    ForEach(backPaddingItems) { item in
                        item.color
                            .containerRelativeFrame(.horizontal, count: visibleItemCount, spacing: spacing)
                    }
                }.scrollTargetLayout()
            }
            .scrollTargetBehavior(.viewAligned)
            .scrollIndicators(.never)
            .scrollPosition(id: $scrollID, anchor: .center)
            
            // Show the current scrollID.
            Text(scrollID?.description ?? "")
        }
        .task {
            for index in 0...20 {
                items.append(.init(id: index, color: .random))
            }
        }
    }
    
    private struct PaddingItem: Identifiable {
        let id = UUID()
        let color = Color.clear
    }
}

struct Item: Identifiable {
    let id: Int
    let color: Color
}


extension Color {
    static var random: Color {
        .init(red: .random(in: 0...1), green: .random(in: 0...1), blue: .random(in: 0...1))
    }
}

To use this in your ContentView, just do

struct ContentView: View {
    var body: some View {
         Carousel(visibleItemCount: 3, spacing: 20)
             .padding()
     }
}

This will create a carousel view that animates as you move, which it seemed like you were trying to do.

Carousel Flicker
 
 
Q