【发布时间】: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