Reputation: 496
Hi am making app which plays video only If it's in the centre of the view. I've already managed to get the position in the scroll view, but I can't combine that with playing the video.
This is my main view:
struct MainView: View {
@State var position = 0.0
var body: some View {
ScrollView {
ForEach(videos){ video in
VideoView(player: video.player)
.onChange(of: position) { pos in
if pos > -50 && pos < 400 {
print("Play video")
}else {
print("Stop video")
}
}
}
.background(GeometryReader {
Color.clear.preference(key: ViewOffsetKey.self, value: -$0.frame(in: .named("scroll")).origin.y)
})
}.onPreferenceChange(ViewOffsetKey.self) {
position = $0
}
.coordinateSpace(name: "scroll")
.padding()
}
}
This is my video model:
struct VideoModel: Identifiable {
var id = UUID()
var number: Int
var player: AVPlayer
}
This is video array:
let videos = [
VideoModel(number: 1, player: AVPlayer(url: URL(fileURLWithPath: Bundle.main.path(forResource: "video", ofType: "mp4")!))),
VideoModel(number: 3, player: AVPlayer(url: URL(fileURLWithPath: Bundle.main.path(forResource: "video", ofType: "mp4")!))),
VideoModel(number: 4, player: AVPlayer(url: URL(fileURLWithPath: Bundle.main.path(forResource: "video", ofType: "mp4")!))),
VideoModel(number: 5, player: AVPlayer(url: URL(fileURLWithPath: Bundle.main.path(forResource: "video", ofType: "mp4")!)))
]
And those are structures handling the video player and preference key:
struct ViewOffsetKey: PreferenceKey {
typealias Value = CGFloat
static var defaultValue = CGFloat.zero
static func reduce(value: inout Value, nextValue: () -> Value) {
value += nextValue()
}
}
struct VideoView: View {
var player: AVPlayer
var body: some View {
AVPlayerControllerRepresented(player: player)
.frame(height: height)
}
}
struct AVPlayerControllerRepresented : UIViewControllerRepresentable {
var player : AVPlayer
func makeUIViewController(context: Context) -> AVPlayerViewController {
let controller = AVPlayerViewController()
controller.player = player
controller.showsPlaybackControls = false
return controller
}
func updateUIViewController(_ uiViewController: AVPlayerViewController, context: Context) {
}
}
Please help, I will be so thankful.
Upvotes: 1
Views: 2030
Reputation: 5094
First You need to make the AVPlayer
a Binding
for the changes in VideoView
& AVPlayerControllerRepresented
to take effect, then add those pieces of code accordingly
player.play() // to play
player.stop() // to stop
Upvotes: 2