【问题标题】:Image carousel with transition effect using swiftUI使用 swiftUI 具有过渡效果的图像轮播
【发布时间】:2020-05-18 13:49:59
【问题描述】:

所以,我几乎从 swiftUI 发布开始就一直在使用它。但是,我正在尝试在我的应用程序中添加一个似乎无法正常工作的新功能。 我想要一个带有过渡效果的图像轮播(自动,意味着图像在定期间隔后发生变化)。经过一番研究,我可能会找到一种方法。但是,它并没有走到一起。 这是我的代码: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()
}
}
}

当应用程序启动时,图像在指定的预定时间间隔后发生变化,即:2s,但所需的过渡(如条纹或圆形)似乎没有任何作用。 (此外,我尝试应用常规的内置过渡,例如幻灯片和不透明度,即使它们不起作用)。 您能帮我找出问题所在,或者其他任何实现相同目标的替代方法吗? 谢谢。

【问题讨论】:

    标签: ios swift xcode swiftui transition


    【解决方案1】:

    发现与您尝试实现的目标有些相似here 这家伙实现了自定义 SwiftUI 视图,可选择自动或通过滑动来设置动画。非常基本的实现,但您仍然可以获得一些想法。

    【讨论】:

    • "鼓励链接到外部资源,但请在链接周围添加上下文,以便您的其他用户了解它是什么以及为什么存在。始终引用重要链接中最相关的部分,以防目标站点无法访问或永久离线。”见How To Answer
    猜你喜欢
    • 2018-01-16
    • 2016-11-18
    • 1970-01-01
    • 1970-01-01
    • 2012-10-30
    • 1970-01-01
    • 2014-03-18
    • 2018-02-23
    • 1970-01-01
    相关资源
    最近更新 更多