I'm running on fumes but logically this view should be showing the share button on the bottom right, and the Title/Date/PlayButton in the middle? What am I doing wrong? It currently just shows the share button underneath
import SwiftUI
import AVKit
struct ContentView: View {
@State private var items = [Item]()
@State private var currentPage = 0
var body: some View {
TabView(selection: $currentPage) {
ForEach(items, id: \.id) { item in
VideoPlayerView(url: item.interactive)
.aspectRatio(contentMode: .fill)
.tag(item.id)
.onAppear {
let controller = AVPlayerViewController()
controller.player = AVPlayer(url: URL(string: item.interactive)!)
controller.showsPlaybackControls = false
controller.player?.play()
}
.overlay(
VStack() {
Spacer()
Text(item.name)
.font(.title)
Text(item.date)
.font(.caption)
Button(action: {
let player = AVPlayer(url: URL(string: item.videolink)!)
let playerController = AVPlayerViewController()
playerController.player = player
playerController.showsPlaybackControls = true
UIApplication.shared.windows.first?.rootViewController?.present(playerController, animated: true, completion: {
player.play()
})
}) {
HStack(spacing: 5) {
Text("PLAY")
Image(systemName: "play.circle")
}
.padding(.horizontal, 10)
.padding(.vertical, 5)
.background(Color.white)
.foregroundColor(.black)
.cornerRadius(20)
}
Button(action: {
let activityVC = UIActivityViewController(activityItems: [URL(string: item.sharelink)!], applicationActivities: nil)
UIApplication.shared.windows.first?.rootViewController?.present(activityVC, animated: true, completion: nil)
}) {
Image(systemName: "square.and.arrow.up.circle")
.foregroundColor(.black)
}
.padding(.bottom, 50)
}
)
}
}
.tabViewStyle(.page)
.onAppear(perform: loadData)
.gesture(DragGesture()
.onEnded { value in
let offset = value.translation.width / UIScreen.main.bounds.width
let newIndex = (CGFloat(currentPage) - offset).rounded()
currentPage = min(max(Int(newIndex), 0), items.count - 1)
}
)
}
func loadData() {
guard let url = URL(string: "jsonfile") else { return }
URLSession.shared.dataTask(with: url) { data, response, error in
guard let data = data else { return }
do {
let decoder = JSONDecoder()
let items = try decoder.decode([Item].self, from: data)
DispatchQueue.main.async {
self.items = items
}
} catch {
print(error.localizedDescription)
}
}.resume()
}
}
struct VideoPlayerView: UIViewRepresentable {
let url: String
func makeUIView(context: Context) -> AVPlayerView {
let view = AVPlayerView()
view.playerLayer.player = AVPlayer(url: URL(string: url)!)
view.playerLayer.videoGravity = .resizeAspectFill
view.playerLayer.backgroundColor = UIColor.black.cgColor
view.playerLayer.player?.play()
return view
}
func updateUIView(_ uiView: AVPlayerView, context: Context) {
// Nothing to update
}
}
class AVPlayerView: UIView {
override class var layerClass: AnyClass {
return AVPlayerLayer.self
}
var playerLayer: AVPlayerLayer {
return layer as! AVPlayerLayer
}
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
let hitView = super.hitTest(point, with: event)
return hitView == self ? nil : hitView
}
}
struct Item: Codable, Identifiable {
let id: Int
let name: String
let interactive: String
let thumbnail: String
let date: String
let videolink: String
let sharelink: String
}
welp I feel dumb... here's a fix for those with the same problem (Zstack)
import SwiftUI
import AVKit
struct ContentView: View {
@State private var items = [Item]()
@State private var currentPage = 0
var body: some View {
TabView(selection: $currentPage) {
ForEach(items, id: \.id) { item in
VideoPlayerView(url: item.interactive)
.aspectRatio(contentMode: .fill)
.tag(item.id)
.onAppear {
let controller = AVPlayerViewController()
controller.player = AVPlayer(url: URL(string: item.interactive)!)
controller.showsPlaybackControls = false
controller.player?.play()
}
.overlay(
ZStack {
VStack() {
Spacer()
Text(item.name)
.font(.title)
Text(item.date)
.font(.caption)
Button(action: {
let player = AVPlayer(url: URL(string: item.videolink)!)
let playerController = AVPlayerViewController()
playerController.player = player
playerController.showsPlaybackControls = true
UIApplication.shared.windows.first?.rootViewController?.present(playerController, animated: true, completion: {
player.play()
})
}) {
Spacer()
HStack(spacing: 5) {
Text("PLAY")
Image(systemName: "play.circle")
}
.padding(.horizontal, 10)
.padding(.vertical, 5)
.background(Color.white)
.foregroundColor(.black)
.cornerRadius(20)
Spacer()
Button(action: {
let activityVC = UIActivityViewController(activityItems: [URL(string: item.sharelink)!], applicationActivities: nil)
UIApplication.shared.windows.first?.rootViewController?.present(activityVC, animated: true, completion: nil)
}) {
Image(systemName: "square.and.arrow.up.circle")
.foregroundColor(.black)
}
}
.padding(.bottom, 50)
.padding(.horizontal, 30)
.frame(width: UIScreen.main.bounds.width)
}
}
)
}
}
.tabViewStyle(.page)
.onAppear(perform: loadData)
.gesture(DragGesture()
.onEnded { value in
let offset = value.translation.width / UIScreen.main.bounds.width
let newIndex = (CGFloat(currentPage) - offset).rounded()
currentPage = min(max(Int(newIndex), 0), items.count - 1)
}
)
}
func loadData() {
guard let url = URL(string: "jsonfile") else { return }
URLSession.shared.dataTask(with: url) { data, response, error in
guard let data = data else { return }
do {
let decoder = JSONDecoder()
let items = try decoder.decode([Item].self, from: data)
DispatchQueue.main.async {
self.items = items
}
} catch {
print(error.localizedDescription)
}
}.resume()
}
}
struct VideoPlayerView: UIViewRepresentable {
let url: String
func makeUIView(context: Context) -> AVPlayerView {
let view = AVPlayerView()
view.playerLayer.player = AVPlayer(url: URL(string: url)!)
view.playerLayer.videoGravity = .resizeAspectFill
view.playerLayer.backgroundColor = UIColor.black.cgColor
view.playerLayer.player?.play()
return view
}
func updateUIView(_ uiView: AVPlayerView, context: Context) {
// Nothing to update
}
}
class AVPlayerView: UIView {
override class var layerClass: AnyClass {
return AVPlayerLayer.self
}
var playerLayer: AVPlayerLayer {
return layer as! AVPlayerLayer
}
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
let hitView = super.hitTest(point, with: event)
return hitView == self ? nil : hitView
}
}
struct Item: Codable, Identifiable {
let id: Int
let name: String
let interactive: String
let thumbnail: String
let date: String
let videolink: String
let sharelink: String
}