Reputation: 1102
In swiftui tv os application avplayercontroller is used to play video. I have added back button as overlay in AVPlayercontroller. Custom back button is not clickable in tvos. The action event does not trigger
struct PlayVideo: View {
@AppStorage("selectedVideo") var videoName : String = "video1. mp4"
@State var player = AVPlayer(url: Bundle.main.url(forResource: "video4",
withExtension: "mp4")!)
@State var isPlaying: Bool = false
let toPresent = UIHostingController(rootView: AnyView(EmptyView()))
@State var path = Bundle.main.path(forResource: "video1", ofType:"mp4")
var body: some View {
// AVPlayerView(videoURL: self.$vURL).transition(.move(edge: .bottom)).edgesIgnoringSafeArea(.all)
// VStack {
// Text("Video player")
AVPlayerView(videoURL: self.$path)
.transition(.move(edge: .bottom))
.edgesIgnoringSafeArea(.all)
.overlay(
VStack(alignment: .leading, spacing: 24)
{
Button(action: {
print("back clicked")
// self.buttonClicked()
}, label: {
HStack {
/* Image("Next")
.frame(width: 15.5, height: 13)
Spacer()
.frame(width: 20)*/
Text("Back")
.font(.interDisplay(.semiBold, size: 20))
.foregroundColor(.black)
.frame(width: 110, height: 44, alignment: .leading)
}
})
.buttonStyle(.automatic)
})
// .frame(width: UIScreen.screenWidth, height: UIScreen.screenHeight-200)
//}
.onAppear {
print("on apper value",videoName)
var videoArray = videoName.components(separatedBy: ".")
var fileName = ""
if videoArray.count > 0 {
fileName = videoArray[0]
}
var fileType = ""
if videoArray.count > 1 {
fileType = videoArray[1]
}
path = Bundle.main.path(forResource: fileName, ofType:fileType)
print("new path is",path)
}
}
}
struct AVPlayerView: UIViewControllerRepresentable {
@Binding var videoURL: String?
@Environment(\.presentationMode) var presentationMode
private var player: AVPlayer {
return AVPlayer(url: URL(fileURLWithPath: videoURL!))
}
func updateUIViewController(_ playerController: AVPlayerViewController, context: Context) {
playerController.modalPresentationStyle = .fullScreen
playerController.player = player
playerController.player?.play()
// Add custom overlay with a back button using SwiftUI Button
let backButton = Button(action: {
print("back action")
context.coordinator.backButtonTapped()
}) {
Text("Back")
}
.padding()
.background(Color.blue) // Customize button appearance as needed
.foregroundColor(.white)
.cornerRadius(8)
.buttonStyle(.card)
// Add the SwiftUI button as a hosting controller
let buttonController = UIHostingController(rootView: backButton)
playerController.addChild(buttonController)
playerController.contentOverlayView?.addSubview(buttonController.view)
// Ensure the button is focusable
buttonController.view.isUserInteractionEnabled = true
buttonController.view.isAccessibilityElement = true
buttonController.view.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
buttonController.view.topAnchor.constraint(equalTo: playerController.contentOverlayView!.topAnchor, constant: 20),
buttonController.view.leadingAnchor.constraint(equalTo: playerController.contentOverlayView!.leadingAnchor, constant: 20),
])
}
func makeUIViewController(context: Context) -> AVPlayerViewController {
let viewController = AVPlayerViewController()
viewController.delegate = context.coordinator
return viewController
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
class Coordinator: NSObject, AVPlayerViewControllerDelegate {
var parent: AVPlayerView
init(_ parent: AVPlayerView) {
self.parent = parent
}
func backButtonTapped() {
print("back clicked")
parent.presentationMode.wrappedValue.dismiss()
}
}
}
How to resolve the issue
I have also tried to add button using zstack but click event not triggered.
struct PlayVideo: View {
@AppStorage("selectedVideo") var videoName : String = "video1. mp4"
@State var player = AVPlayer(url: Bundle.main.url(forResource: "video1",
withExtension: "mp4")!)
@State var isPlaying: Bool = false
/* var body: some View {
VStack {
VideoPlayer(player: player)
.frame(width: UIScreen.screenWidth, height: UIScreen.screenHeight-200, alignment: .top)
Button {
isPlaying ? player.pause() : player.play()
isPlaying.toggle()
player.seek(to: .zero)
} label: {
Image(systemName: isPlaying ? "stop" : "play")
.padding()
}
}
}*/
let toPresent = UIHostingController(rootView: AnyView(EmptyView()))
@State var path = Bundle.main.path(forResource: "video1", ofType:"mp4")
// @State private var vURL = URL(string: "https://www.radiantmediaplayer.com/media/bbb-360p.mp4")
var body: some View {
// AVPlayerView(videoURL: self.$vURL).transition(.move(edge: .bottom)).edgesIgnoringSafeArea(.all)
// VStack {
// Text("Video player")
ZStack {
AVPlayerView(videoURL: self.$path)
.transition(.move(edge: .bottom))
.edgesIgnoringSafeArea(.all)
VStack(alignment: .leading, spacing: 24)
{
Button(action: {
print("back clicked")
// self.buttonClicked()
}, label: {
HStack {
/* Image("Next")
.frame(width: 15.5, height: 13)
Spacer()
.frame(width: 20)*/
Text("Back")
.font(.interDisplay(.semiBold, size: 20))
.foregroundColor(.black)
.frame(width: 110, height: 44, alignment: .leading)
}
})
.buttonStyle(.card)
.zIndex(1)
}
}
/* .overlay(
VStack(alignment: .leading, spacing: 24)
{
Button(action: {
print("back clicked")
// self.buttonClicked()
}, label: {
HStack {
/* Image("Next")
.frame(width: 15.5, height: 13)
Spacer()
.frame(width: 20)*/
Text("Back")
.font(.interDisplay(.semiBold, size: 20))
.foregroundColor(.black)
.frame(width: 110, height: 44, alignment: .leading)
}
})
.buttonStyle(.automatic)
.zIndex(1)
})*/
// .frame(width: UIScreen.screenWidth, height: UIScreen.screenHeight-200)
//}
.onAppear {
print("on apper value",videoName)
var videoArray = videoName.components(separatedBy: ".")
var fileName = ""
if videoArray.count > 0 {
fileName = videoArray[0]
}
var fileType = ""
if videoArray.count > 1 {
fileType = videoArray[1]
}
path = Bundle.main.path(forResource: fileName, ofType:fileType)
print("new path is",path)
}
}
}
Upvotes: 0
Views: 83