SwiftUI:在CarouselView中实现定时器



我遵循了本教程。。https://www.youtube.com/watch?v=fB5MzDD1PZI&list=WL&索引=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
}
}
}

Ps。很抱歉误解了规则。我是StackOverFlow和SwiftUI的新手。谢谢你。

检查一下:

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()
}
}

最新更新