By P. Ent


2020-07-31 20:24:14 8 Comments

I have this simple View that takes an array of Views. The idea is that clicking on the visible view slides the next view into place. This is working fine if I index my Views array with constants but does not work if the index is a @State var.

This is what is NOT working:

struct ImageCarousel<Page : View>: View {
    let pages:[Page]
    @State private var currentImage = 0
    init(_ views:[Page]) {
        pages = views
    }
    var body: some View {
        VStack {
            pages[self.currentImage]
                .transition(.slide)
                .animation(.easeInOut)
                .onTapGesture {
                    withAnimation {
                        self.currentImage = self.currentImage+1 >= self.pages.count ? 0 : self.currentImage+1
                    }
            }
        }
    }
}

But this version of body does work but is not useful:

var body: some View {
    VStack {
        if self.currentImage == 0 {
            pages[0]
                .transition(.slide)
                .animation(.easeInOut)
                .onTapGesture {
                    withAnimation {
                        self.currentImage = 1
                    }
            }
        } else {
            pages[1]
                .transition(.slide)
                .animation(.easeInOut)
                .onTapGesture {
                    withAnimation {
                        self.currentImage = 0
                    }
            }
        }
    }
}

If I do not have the IF statement and just use pages[self.currentImage] the transition does not work.

You would use this View this like:

ImageCarousel([
            Rectangle().foregroundColor(.red),
            Rectangle().foregroundColor(.orange),
            Rectangle().foregroundColor(.yellow),
            Rectangle().foregroundColor(.green),
            Rectangle().foregroundColor(.blue),
            Rectangle().foregroundColor(.purple)
        ])

Any insight is greatly appreciated. I feel like this is something obvious that I am not seeing.

1 comments

@P. Ent 2020-08-01 13:50:29

I came up with a solution that isn't too complicated (more of a hack): Temporarily replace the current View with a dummy View and when that appears, trigger the next View to appear. This satisfies the condition of removing a View and replacing it with another View:

var body: some View {
    ZStack {
        if self.currentImage == -1 {
            Rectangle()
                .foregroundColor(.gray)
                .onAppear {
                    self.currentImage = self.nextImage
            }
        } else {
            pages[self.nextImage]
                .transition(.slide)
                .animation(.easeInOut)
                .onTapGesture {
                    withAnimation {
                        self.nextImage = self.nextImage+1 >= self.pages.count ? 0 : self.nextImage+1
                        self.currentImage = -1
                    }
            }
        }
    }
}

This works fine for this simplified case. I did not really want to go into UIScrollView or UIPageViewController territory if I didn't have to.

Related Questions

Sponsored Content

44 Answered Questions

[SOLVED] Passing Data between View Controllers

1 Answered Questions

2 Answered Questions

How to reset child view state variable with SwiftUI?

  • 2020-04-08 21:37:50
  • GSD
  • 208 View
  • 0 Score
  • 2 Answer
  • Tags:   swiftui

1 Answered Questions

1 Answered Questions

[SOLVED] SwiftUI page control implementation

  • 2019-08-07 09:53:11
  • f3dm76
  • 2102 View
  • 0 Score
  • 1 Answer
  • Tags:   swiftui

1 Answered Questions

[SOLVED] d3 js transition over the array of rectangles does not work

1 Answered Questions

[SOLVED] Use a contained view controller to manage carousel animations or not?

  • 2013-04-11 17:37:47
  • Gruntcakes
  • 365 View
  • 0 Score
  • 1 Answer
  • Tags:   ios

Sponsored Content