SwiftUI:在 CarouselView 中实现定时器
Posted
技术标签:
【中文标题】SwiftUI:在 CarouselView 中实现定时器【英文标题】:SwiftUI: Implementing Timer into CarouselView 【发布时间】:2020-03-30 14:56:21 【问题描述】:我遵循了这个教程..https://www.youtube.com/watch?v=fB5MzDD1PZI&list=WL&index=32&t=0s
我正在尝试将计时器添加到它,因为它会自动转到下一张图像。有什么建议吗?谢谢。
这是我当前的代码,缺少一些代码,我不知道下一步该做什么。
import SwiftUI
struct ContentView: View
let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
@State var Counter = 0
var body: some View
ZStack
VStack
Text("HELLOWORLD")
VStack
CarouselView(itemHeight: 400, views: [
AnyView(Text("1")),
AnyView(Text("2")),
AnyView(Text("3")),
AnyView(Text("4")),
AnyView(Text("5")),
AnyView(Text("6")),
]).onReceive(timer) _ in
if self.Counter > 0
self.Counter -= 1
//missing some code to move index of carousel to i+1
Button(action:
self.Counter = 10
)
Text("RUN")
struct CarouselView: View
@GestureState private var dragState = DragState.inactive
@State var carouselLocation = 0
var itemHeight:CGFloat
var views:[AnyView]
private func onDragEnded(drag: DragGesture.Value)
print("drag ended")
let dragThreshold:CGFloat = 200
if drag.predictedEndTranslation.width > dragThreshold || drag.translation.width > dragThreshold
carouselLocation = carouselLocation - 1
else if (drag.predictedEndTranslation.width) < (-1 * dragThreshold) || (drag.translation.width) < (-1 * dragThreshold)
carouselLocation = carouselLocation + 1
var body: some View
ZStack
VStack
ZStack
ForEach(0..<views.count)i in
VStack
Spacer()
self.views[i]
//Text("\(i)")
.frame(width:300, height: self.getHeight(i))
.animation(.interpolatingSpring(stiffness: 300.0, damping: 30.0, initialVelocity: 10.0))
.background(Color.white)
.cornerRadius(10)
.shadow(radius: 3)
.opacity(self.getOpacity(i))
.animation(.interpolatingSpring(stiffness: 300.0, damping: 30.0, initialVelocity: 10.0))
.offset(x: self.getOffset(i))
.animation(.interpolatingSpring(stiffness: 300.0, damping: 30.0, initialVelocity: 10.0))
Spacer()
.gesture(
DragGesture()
.updating($dragState) drag, state, transaction in
state = .dragging(translation: drag.translation)
.onEnded(onDragEnded)
)
Spacer()
VStack
Spacer()
Spacer().frame(height:itemHeight + 50)
Text("\(relativeLoc() + 1)/\(views.count)").padding()
Spacer()
func relativeLoc() -> Int
return ((views.count * 10000) + carouselLocation) % views.count
func getHeight(_ i:Int) -> CGFloat
if i == relativeLoc()
return itemHeight
else
return itemHeight - 100
func getOpacity(_ i:Int) -> Double
if i == relativeLoc()
|| i + 1 == relativeLoc()
|| i - 1 == relativeLoc()
|| i + 2 == relativeLoc()
|| i - 2 == relativeLoc()
|| (i + 1) - views.count == relativeLoc()
|| (i - 1) + views.count == relativeLoc()
|| (i + 2) - views.count == relativeLoc()
|| (i - 2) + views.count == relativeLoc()
return 1
else
return 0
func getOffset(_ i:Int) -> CGFloat
//This sets up the central offset
if (i) == relativeLoc()
//Set offset of cental
return self.dragState.translation.width
//These set up the offset +/- 1
else if
(i) == relativeLoc() + 1
||
(relativeLoc() == views.count - 1 && i == 0)
//Set offset +1
return self.dragState.translation.width + (300 + 20)
else if
(i) == relativeLoc() - 1
||
(relativeLoc() == 0 && (i) == views.count - 1)
//Set offset -1
return self.dragState.translation.width - (300 + 20)
//These set up the offset +/- 2
else if
(i) == relativeLoc() + 2
||
(relativeLoc() == views.count-1 && i == 1)
||
(relativeLoc() == views.count-2 && i == 0)
return self.dragState.translation.width + (2*(300 + 20))
else if
(i) == relativeLoc() - 2
||
(relativeLoc() == 1 && i == views.count-1)
||
(relativeLoc() == 0 && i == views.count-2)
//Set offset -2
return self.dragState.translation.width - (2*(300 + 20))
//These set up the offset +/- 3
else if
(i) == relativeLoc() + 3
||
(relativeLoc() == views.count-1 && i == 2)
||
(relativeLoc() == views.count-2 && i == 1)
||
(relativeLoc() == views.count-3 && i == 0)
return self.dragState.translation.width + (3*(300 + 20))
else if
(i) == relativeLoc() - 3
||
(relativeLoc() == 2 && i == views.count-1)
||
(relativeLoc() == 1 && i == views.count-2)
||
(relativeLoc() == 0 && i == views.count-3)
//Set offset -2
return self.dragState.translation.width - (3*(300 + 20))
//This is the remainder
else
return 10000
enum DragState
case inactive
case dragging(translation: CGSize)
var translation: CGSize
switch self
case .inactive:
return .zero
case .dragging(let translation):
return translation
var isDragging: Bool
switch self
case .inactive:
return false
case .dragging:
return true
附言。对不起,误解了规则。我是 *** 和 SwiftUI 的新手。谢谢你。
【问题讨论】:
你试过什么?你遇到了什么问题? 嗨河马,欢迎来到***。请阅读***.com/help/how-to-ask。这不是“我们为您编写代码”的平台,而是“我们帮助您编写代码”的平台。所以向我们展示您尝试过的代码...它应该可以运行并重现您的问题。 请不要破坏您自己的帖子。当您在此处发帖时,您授予 SO 根据 CC-by SA 4.0 分发内容的权利。任何破坏行为都将被撤销。 【参考方案1】:看看这个:
import SwiftUI
struct ContentView: View
@State var location : Int = 0
let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
@State var Counter = 0
var body: some View
ZStack
VStack
Text("HELLOWORLD")
VStack
CarouselView(carouselLocation: self.$location, itemHeight: 400, views: [
AnyView(Text("1")),
AnyView(Text("2")),
AnyView(Text("3")),
AnyView(Text("4")),
AnyView(Text("5")),
AnyView(Text("6")),
]).onReceive(timer) _ in
if self.Counter > 0
self.Counter -= 1
//missing some code to move index of carousel to i+1
Button(action:
self.Counter = 10
Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) (timer) in
self.location += 1
)
Text("RUN")
struct CarouselView: View
@GestureState private var dragState = DragState.inactive
@Binding var carouselLocation : Int
var itemHeight:CGFloat
var views:[AnyView]
private func onDragEnded(drag: DragGesture.Value)
print("drag ended")
let dragThreshold:CGFloat = 200
if drag.predictedEndTranslation.width > dragThreshold || drag.translation.width > dragThreshold
carouselLocation = carouselLocation - 1
else if (drag.predictedEndTranslation.width) < (-1 * dragThreshold) || (drag.translation.width) < (-1 * dragThreshold)
carouselLocation = carouselLocation + 1
var body: some View
ZStack
VStack
ZStack
ForEach(0..<views.count)i in
VStack
Spacer()
self.views[i]
//Text("\(i)")
.frame(width:300, height: self.getHeight(i))
.animation(.interpolatingSpring(stiffness: 300.0, damping: 30.0, initialVelocity: 10.0))
.background(Color.white)
.cornerRadius(10)
.shadow(radius: 3)
.opacity(self.getOpacity(i))
.animation(.interpolatingSpring(stiffness: 300.0, damping: 30.0, initialVelocity: 10.0))
.offset(x: self.getOffset(i))
.animation(.interpolatingSpring(stiffness: 300.0, damping: 30.0, initialVelocity: 10.0))
Spacer()
.gesture(
DragGesture()
.updating($dragState) drag, state, transaction in
state = .dragging(translation: drag.translation)
.onEnded(onDragEnded)
)
Spacer()
VStack
Spacer()
Spacer().frame(height:itemHeight + 50)
Text("\(relativeLoc() + 1)/\(views.count)").padding()
Spacer()
func relativeLoc() -> Int
return ((views.count * 10000) + carouselLocation) % views.count
func getHeight(_ i:Int) -> CGFloat
if i == relativeLoc()
return itemHeight
else
return itemHeight - 100
func getOpacity(_ i:Int) -> Double
if i == relativeLoc()
|| i + 1 == relativeLoc()
|| i - 1 == relativeLoc()
|| i + 2 == relativeLoc()
|| i - 2 == relativeLoc()
|| (i + 1) - views.count == relativeLoc()
|| (i - 1) + views.count == relativeLoc()
|| (i + 2) - views.count == relativeLoc()
|| (i - 2) + views.count == relativeLoc()
return 1
else
return 0
func getOffset(_ i:Int) -> CGFloat
//This sets up the central offset
if (i) == relativeLoc()
//Set offset of cental
return self.dragState.translation.width
//These set up the offset +/- 1
else if
(i) == relativeLoc() + 1
||
(relativeLoc() == views.count - 1 && i == 0)
//Set offset +1
return self.dragState.translation.width + (300 + 20)
else if
(i) == relativeLoc() - 1
||
(relativeLoc() == 0 && (i) == views.count - 1)
//Set offset -1
return self.dragState.translation.width - (300 + 20)
//These set up the offset +/- 2
else if
(i) == relativeLoc() + 2
||
(relativeLoc() == views.count-1 && i == 1)
||
(relativeLoc() == views.count-2 && i == 0)
return self.dragState.translation.width + (2*(300 + 20))
else if
(i) == relativeLoc() - 2
||
(relativeLoc() == 1 && i == views.count-1)
||
(relativeLoc() == 0 && i == views.count-2)
//Set offset -2
return self.dragState.translation.width - (2*(300 + 20))
//These set up the offset +/- 3
else if
(i) == relativeLoc() + 3
||
(relativeLoc() == views.count-1 && i == 2)
||
(relativeLoc() == views.count-2 && i == 1)
||
(relativeLoc() == views.count-3 && i == 0)
return self.dragState.translation.width + (3*(300 + 20))
else if
(i) == relativeLoc() - 3
||
(relativeLoc() == 2 && i == views.count-1)
||
(relativeLoc() == 1 && i == views.count-2)
||
(relativeLoc() == 0 && i == views.count-3)
//Set offset -2
return self.dragState.translation.width - (3*(300 + 20))
//This is the remainder
else
return 10000
enum DragState
case inactive
case dragging(translation: CGSize)
var translation: CGSize
switch self
case .inactive:
return .zero
case .dragging(let translation):
return translation
var isDragging: Bool
switch self
case .inactive:
return false
case .dragging:
return true
struct ContentView_Previews: PreviewProvider
static var previews: some View
ContentView()
【讨论】:
以上是关于SwiftUI:在 CarouselView 中实现定时器的主要内容,如果未能解决你的问题,请参考以下文章