in SwiftUI I add a Videoplayer, but the frame is not really 16:9, but the video's are.
private let player = AVPlayer(url: URL(string: UserDefaults.standard.string(forKey: "videoURL") ?? "https://www.learningcontainer.com/wp-content/uploads/2020/05/sample-mp4-file.mp4")!)
With this view:
ZStack {
VideoPlayer(player: player)
.onAppear() {
player.play()
}.frame(
idealWidth: .infinity,
maxWidth: .infinity,
idealHeight: (UIScreen.main.bounds.height / 3) * 1.75,
maxHeight: UIScreen.main.bounds.height - 600,
alignment: .center
)
}
.background(
RoundedRectangle(cornerRadius: 40.0)
.stroke(Color(.red), lineWidth: 5)
.overlay(
RoundedRectangle(cornerRadius: 40.0)
.fill(Color(.black))
)
)
The Player is working and shown correctly, but with a black background on the both sides.. I want it red, so it does look prettier than random black in the red block.
Is there a way to change the background color of the black sideparts? I tried edgesIgnoringSafeArea
with no luck.
Little but of how it looks like now, where you see the black "borders" on the side;
Use AVPlayerLayer
with the help of UIViewRepresentable
and set the AVPlayerLayer
layer color as you want.
PlayerUIView
class PlayerUIView: UIView {
// MARK: Class Property
let playerLayer = AVPlayerLayer()
// MARK: Init
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
init(player: AVPlayer) {
super.init(frame: .zero)
self.playerSetup(player: player)
}
deinit {
NotificationCenter.default.removeObserver(self)
}
// MARK: Life-Cycle
override func layoutSubviews() {
super.layoutSubviews()
playerLayer.frame = bounds
}
// MARK: Class Methods
private func playerSetup(player: AVPlayer) {
playerLayer.player = player
player.actionAtItemEnd = .none
layer.addSublayer(playerLayer)
playerLayer.backgroundColor = UIColor.red.cgColor // <--- Set color here
}
}
PlayerView
struct PlayerView: UIViewRepresentable {
@Binding var player: AVPlayer
func makeUIView(context: Context) -> PlayerUIView {
return PlayerUIView(player: player)
}
func updateUIView(_ uiView: PlayerUIView, context: UIViewRepresentableContext<PlayerView>) {
uiView.playerLayer.player = player
}
}
Usage
struct ContentView: View {
@State private var player = AVPlayer(url: URL(string: UserDefaults.standard.string(forKey: "videoURL") ?? "https://www.learningcontainer.com/wp-content/uploads/2020/05/sample-mp4-file.mp4")!)
var body: some View {
ZStack {
PlayerView(player: $player)
.onAppear() {
player.play()
}.ignoresSafeArea()
}
}
}
EDIT
For video controller, use bellow code.
struct PlayerView: UIViewRepresentable {
@Binding var player: AVPlayer
func makeUIView(context: Context) -> PlayerUIView {
return PlayerUIView(player: player)
}
func updateUIView(_ uiView: PlayerUIView, context: UIViewRepresentableContext<PlayerView>) {
uiView.playerViewController.player = player
}
}
class PlayerUIView: UIView {
// MARK: Class Property
let playerViewController = AVPlayerViewController()
// MARK: Init
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
init(player: AVPlayer) {
super.init(frame: .zero)
self.playerSetup(player: player)
}
// MARK: Life-Cycle
override func layoutSubviews() {
super.layoutSubviews()
playerViewController.view.frame = bounds
}
// MARK: Class Methods
private func playerSetup(player: AVPlayer) {
playerViewController.player = player
playerViewController.view.backgroundColor = .red
self.addSubview(playerViewController.view)
}
}
You also do not need to set the background view.