1

I want to create a Carousel with SwiftUI(without using TabView) with a matching/linked Page Control in SwiftUI

So far I have both views and can update the pageControl view with a @State var pagecontrolTracker updated with a DragGesture() .onChanged but it doesn't update the PageControl if I scroll fast, or sometimes doesn't update at all . If I Scroll slow tho, the Page Control does update sometimes as expected.

Is there a better way to update this faster and smoother? I saw .updating modifier for DragGesture() but this doesn't work either

Full View:

struct ContentView: View {
    
    @State var pagecontrolTracker: Int  = 0
    
    var body: some View {
        VStack {
            ScrollView(.horizontal) {
                HStack {
                    ForEach(0...3, id: \.self) { index in
                       PagingRow()
                            .gesture(DragGesture().onChanged({ _ in
                                pagecontrolTracker = index
                            }))
                    }
                }
            }
            
            PagingControls(pagecontrolTracker: $pagecontrolTracker)
            
        }
        .padding()
    }
}

Inside Custom SwiftUI Row View

struct PagingRow: View {
    
    
    var body: some View {
        VStack {
            HStack {
                Image(systemName: "globe")
                
                Text("Test Title")
                
            }
            .padding()
            
            Button {
                print("Test action")
            } label: {
                Text("Tap Me")
            }
            .buttonStyle(.borderedProminent)
            .padding()
        }
        .background(Color.orange)
        .frame(width: 200)
        .cornerRadius(8)
    }
}

Custom PageControl in SwiftUI

struct PagingControls: View {
    
    @Binding var pagecontrolTracker: Int
    
    var body: some View {
        HStack {
            ForEach(0...3, id: \.self) { pagingIndex in
                Circle()
                    .fill(pagecontrolTracker == pagingIndex ? .orange : .black)
                    .frame(width: 8, height: 8)
            }
        }
    }
}

Scrolling updates the SwiftUI Pagecontrol slow

Note: I don't want to use TabView since I want to be able to show the next upcoming card in the scrollView

A TabView would only show one card per page

Di Nerd Apps
  • 770
  • 8
  • 15
  • If you are looking to have it work like a typical carousel, you could use a TabView. This would change the style a bit, but would effectively work as you described. If interested, I could post a TabView example. – nickreps Dec 04 '22 at 18:02
  • Nah TabView won't work because, I want a part of the next upcoming card to show while the main one is still being presented a TabView would only show 1 per page, without a preview of the next upcoming card – Di Nerd Apps Dec 04 '22 at 21:12
  • check out the response by steppenwolf123 - it appears to be a side effect of the scrollview taking over and cancelling the drag gesture. This explains why it works when you scroll slowly, but not when scrolling quickly: https://developer.apple.com/forums/thread/655465?answerId=680397022#680397022 – nickreps Dec 05 '22 at 00:49

0 Answers0