Video gravity as per .
I needed this because VideoGravity.aspectResizeFill
does exactly what I need:
The video preserves its aspect ratio and fills the layer’s bounds.
...
This gravity value may crop the video image along its horizontal or vertical dimension.
I have tried many workarounds including hardcoding the aspect ratio as recommended here, but they were unsatisfactory.
Video gravity as per https://developer.apple/documentation/avfoundation/avplayerlayer/videogravity.
I needed this because VideoGravity.aspectResizeFill
does exactly what I need:
The video preserves its aspect ratio and fills the layer’s bounds.
...
This gravity value may crop the video image along its horizontal or vertical dimension.
I have tried many workarounds including hardcoding the aspect ratio as recommended here, but they were unsatisfactory.
Share Improve this question asked Mar 25 at 2:03 Wong Jia HauWong Jia Hau 3,1092 gold badges24 silver badges40 bronze badges1 Answer
Reset to default 1This is a particularly tricky question because Video Gravity was introduced in 2014 while SwiftUI was only released in 2019. For reasons unknown, the Video Gravity API was not being ported from UIKit to SwifUI.
Thus, to use Video Gravity in SwiftUI, we have to create a SwiftUI wrapper around a UIKit view as follows:
import AVKit
import SwiftUI
class PlayerUIView: UIView {
private let playerLayer = AVPlayerLayer()
private var player: AVPlayer?
// Default initializer with frame
override init(frame: CGRect) {
super.init(frame: frame)
setupLayer()
}
// Required initializer when using Interface Builder
required init?(coder: NSCoder) {
super.init(coder: coder)
setupLayer()
}
// Setup the player layer
private func setupLayer() {
playerLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill
layer.addSublayer(playerLayer)
}
// Set a new player
func setPlayer(_ player: AVPlayer, gravity: AVLayerVideoGravity) {
self.player = player
playerLayer.player = player
playerLayer.videoGravity = gravity
}
override func layoutSubviews() {
super.layoutSubviews()
playerLayer.frame = bounds
}
}
struct MyVideoPlayerView: UIViewRepresentable {
var player: AVPlayer
var videoGravity: AVLayerVideoGravity
func makeUIView(context _: Context) -> PlayerUIView {
let view = PlayerUIView(frame: .zero)
view.setPlayer(player, gravity: videoGravity)
return view
}
func updateUIView(_: PlayerUIView, context _: Context) {
// Update the view if needed
}
}
Usage example:
import AVKit
import SwiftUI
struct MyView: View {
let player = AVPlayer(url: URL(string: "https://myvideo/abc")!)
var body: some View {
MyVideoPlayerView(
player: player,
videoGravity: .resizeAspectFill
)
.ignoresSafeArea() // For displaying the video in full screen
}
}