I'm trying to recreate the Unfold App Subscription screen with an horizontal carousel of images that are moving automatically from right to left with enabled gestures to move right or left, and then the animation continues again.
I found a way to animate an horizontal ScrollView using 3 modifiers:
But when I'm dragging the carousel, I can't find a way to have the x coordinate changed to where I left.
If anyone has an idea how to solve that issue, that would be life-saving!
Here's the SwiftUI code I wrote:
import SwiftUI
import AVKit
struct ContentView: View {
@State var scrollText = false
var body: some View {
ZStack {
VStack {
Color(#colorLiteral(red: 0, green: 0, blue: 0, alpha: 1))
.ignoresSafeArea(.all)
}
VStack {
VideoPlayer(player: AVPlayer(url: Bundle.main.url(forResource: "wave-1", withExtension: "mp4")!)) {
VStack {
Image("pro-text")
.resizable()
.frame(width: 150, height: .infinity)
.scaledToFit()
}
}
.ignoresSafeArea(.all)
.frame(width: .infinity, height: 300)
ScrollView(.horizontal, showsIndicators: false) {
HStack(spacing: 5) {
Image("benefit-1")
.resizable()
.frame(width: 120, height: 120)
Image("benefit-2")
.resizable()
.frame(width: 120, height: 120)
Image("benefit-3")
.resizable()
.frame(width: 120, height: 120)
Image("benefit-4")
.resizable()
.frame(width: 120, height: 120)
Image("benefit-5")
.resizable()
.frame(width: 120, height: 120)
}
.offset(x: scrollText ? -500 : 20)
.animation(Animation.linear(duration: 30).repeatForever(autoreverses: false))
.onAppear() {
self.scrollText.toggle()
}
}
Spacer()
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Sharing here the answer from my other post.
Because duration doesn't seem to work with withAnimation yet, I had to be a bit hacky to get the animation effect I wanted.
Here's what I did:
Here's what my code looks like:
import SwiftUI
import AVKit
struct ProView: View {
@State private var scrollText = false
var body: some View {
ZStack {
// VStack {
// Color(#colorLiteral(red: 0, green: 0, blue: 0, alpha: 1))
// .ignoresSafeArea(.all)
// }
//
// VStack {
//
// VideoPlayer(player: AVPlayer(url: Bundle.main.url(forResource: "wave-1", withExtension: "mp4")!)) {
// VStack {
// Image("pro-text")
// .resizable()
// .frame(width: 200, height: .infinity)
// .scaledToFit()
// }
// }
// .ignoresSafeArea(.all)
// .frame(width: .infinity, height: 300)
ScrollView(.horizontal, showsIndicators: false) {
ScrollViewReader { value in
HStack(spacing: 5) {
ForEach(0 ..< 100) { i in
HStack {
Image("benefit-1")
.resizable()
.frame(width: 120, height: 120)
Image("benefit-2")
.resizable()
.frame(width: 120, height: 120)
Image("benefit-3")
.resizable()
.frame(width: 120, height: 120)
Image("benefit-4")
.resizable()
.frame(width: 120, height: 120)
Image("benefit-5")
.resizable()
.frame(width: 120, height: 120)
Image("benefit-6")
.resizable()
.frame(width: 120, height: 120)
Image("benefit-7")
.resizable()
.frame(width: 120, height: 120)
Image("benefit-8")
.resizable()
.frame(width: 120, height: 120)
Image("benefit-9")
.resizable()
.frame(width: 120, height: 120)
Image("benefit-10")
.resizable()
.frame(width: 120, height: 120)
}
.id(i)
}
}
.offset(x: scrollText ? -10000 : 20)
.animation(Animation.linear(duration: 300).repeatForever(autoreverses: false))
.onAppear() {
value.scrollTo(50, anchor: .trailing)
scrollText.toggle()
}
}
}
Spacer()
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ProView()
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.