0

So, I've been using swiftUI almost from the time of it's release and playing around with it. However, I'm trying to add a new feature into my app which doesn't seem to work as desired. I want to have an Image carousel(automatic, meaning the image change after a regular interval) with transition effect. After doing a bit of research ,I could possibly find a method to do so. But, it's not coming together. Here's my code: SwipeImages.swift

    import SwiftUI
    struct SwipeImages:View{

    @State private var difference: CGFloat = 0
    @State private var index = 0

    let spacing:CGFloat = 10




    var timer: Timer{

        Timer.scheduledTimer(withTimeInterval: 2, repeats: true) { (timer) in

            if self.index < images.count - 1{
                self.index += 1
            }
            else{
                self.index = 0
            }
        }
    }

    var body:some View{

        ContentView(imageData: images[self.index])
            .onAppear {
                let _ = self.timer
        }
    }

}

    public struct ImageData:Identifiable{
        public let id:Int
        let image:String
        let title:String
        let country:String
    }

        let images = [ImageData(id:0,image:"1a.jpg",title: "String1", country: "country1"),
                      ImageData(id:1,image:"2a.jpg",title: "String2", country: "country2"),
                      ImageData(id:2,image:"3a.jpg",title: "String3", country: "country3")]

ContentView.swift

    import SwiftUI


struct ContentView:View{

    let imageData:ImageData

    var transitionStyle:Int = 1

    var transition:AnyTransition{

        switch transitionStyle{

        case 0:
            return .opacity
        case 1:
            return .circular
        case 2:
            return .stripes(stripes:50,horizontal:true)
        default:
            return .opacity

        }
    }

    var body:some View{
        ZStack{


            Image(uiImage: UIImage(named: "\(imageData.image)")!)
                .resizable()
                .transition(self.transition)
                .overlay(
                    Rectangle()
                        .fill(LinearGradient(gradient: Gradient(colors: [.clear,.black]), startPoint: .center, endPoint: .bottom))
                        .clipped()
            )
                .cornerRadius(2.0)



            VStack(alignment: .leading) {

                    Spacer()
                Text("\(imageData.title)")
                        .font(.title)
                        .fontWeight(.semibold)
                        .foregroundColor(.white)
                Text(imageData.country)
                    .foregroundColor(.white)

                }
            .padding()
        }
        .shadow(radius:12.0)
        .cornerRadius(12.0)

    }
}


extension Image{
    func imageStyle(height:CGFloat) -> some View{
        let shape = RoundedRectangle(cornerRadius: 15.0)

        return self.resizable()
            .frame(height:height)
            .overlay(
                Rectangle()
                    .fill(LinearGradient(gradient: Gradient(colors: [.clear,.black]), startPoint: .center, endPoint: .bottom))
                .clipped()
            )
                .cornerRadius(2.0)
        .clipShape(shape)

    }
}


extension AnyTransition{

    static var circular: AnyTransition{
        get{
            AnyTransition.modifier(active: ShapeClipModifier(shape: CircleClipShape(pct:1)), identity: ShapeClipModifier(shape: CircleClipShape(pct:0)))
        }
    }

    static func stripes(stripes s:Int,horizontal isHorizontal:Bool) -> AnyTransition{

        return AnyTransition.asymmetric(insertion: AnyTransition.modifier(active: ShapeClipModifier(shape:StripeShape(insertion:true,pct:1,stripes:s,horizontal:isHorizontal)), identity:
            ShapeClipModifier(shape:StripeShape(insertion:true,pct:0,stripes:s,horizontal:isHorizontal))
            ), removal:AnyTransition.modifier(active:             ShapeClipModifier(shape:StripeShape(insertion:false,pct:1,stripes:s,horizontal:isHorizontal))
                , identity:
                ShapeClipModifier(shape:StripeShape(insertion:false,pct:0,stripes:s,horizontal:isHorizontal)))
        )
    }


}

struct ShapeClipModifier<S: Shape>: ViewModifier{
    let shape: S

    func body(content:Content) -> some View {
        content.clipShape(shape)
    }
}


struct StripeShape: Shape{

    let insertion: Bool
    var pct: CGFloat
    let stripes: Int
    let horizontal: Bool

    var animatableData: CGFloat{
        get{pct}

        set{pct = newValue}
    }

    func path(in rect:CGRect) -> Path{

        var path = Path()


        let stripeHeight = rect.height/CGFloat(stripes)


        for i in 0..<stripes{

            let iteratorValue = CGFloat(i)

                if insertion{

                    path.addRect(CGRect(x: 0, y: iteratorValue * stripeHeight, width: rect.width, height: stripeHeight * (1 - pct)))
                }
                else{
                    path.addRect(CGRect(x: 0, y: iteratorValue * stripeHeight + (stripeHeight * pct), width: rect.width, height: stripeHeight * (1 - pct)))
            }

        }

        return path

    }
}

struct CircleClipShape: Shape{

    var pct:CGFloat

    var animatableData: CGFloat{
        get{pct}

        set{pct = newValue}
    }

    func path(in rect: CGRect) -> Path {
        var path = Path()
        var bigRect = rect
        bigRect.size.width = bigRect.size.width * 2 * (1-pct)
        bigRect.size.height = bigRect.size.height * 2 * (1-pct)
        bigRect = bigRect.offsetBy(dx: -rect.width/2.0, dy: -rect.height/2.0)

        path = Circle().path(in: bigRect)

        return path
    }


}

MainView.swift

   import SwiftUI
struct MainView:View{
var body:some View{
VStack{
SwipeImages()
.padding()
}
}
}

When the app is launched the images change after scheduled interval specified ,i.e: 2s , but the required transition such as stripes or circular ,nothing seem to come in action. (Also, I tried applying regular inbuilt transitions such as slide and opacity, even they aren't working). Could you please help me identifying what's wrong, or any other alternatives to achieve the same? Thanks.

Prajwal Kulkarni
  • 1,480
  • 13
  • 22

1 Answers1

0

Found somewhat similar to what you are trying to achieve here The guy implemented custom SwiftUI view, with option to animate automatically or by swiping. Very basic implementation but still you can get some ideas.

Bacterial
  • 3
  • 3
  • "Links to external resources are encouraged, but please add context around the link so your fellow users will have some idea what it is and why it’s there. Always quote the most relevant part of an important link, in case the target site is unreachable or goes permanently offline." See [How To Answer](https://stackoverflow.com/help/how-to-answer) – jasie Sep 03 '20 at 08:01