Search code examples
xcodevideoswiftuiframeavkit

SwiftUI, How to resize a video to fill all vertical (iPhone) while maintaining aspect ratio (left and right not visible edges off screen)


I have a video that is suitable for viewing on a tv or laptop (i.e. landscape dominant). I need to make this video fill an iPhone screen vertically without stretching the video out of aspect. Consequently much of the left and right of the video will bleed off the left and right sides of the screen.

CodingWithChris did exactly this in storyboard form here: https://www.youtube.com/watch?v=1HN7usMROt8 (zoom ahead to 1:35:00) I need to know how to do this in SwiftUI programmatically.

Currently I have a video that plays in the simulator onAppear. Here is my code:

struct SignInView: View {

private let player = AVPlayer(url: URL(fileURLWithPath: Bundle.main.path(forResource: "DL_preview", ofType: "mp4")!))

var body: some View {
    
    ZStack {
        VideoPlayer(player: player)
            .onAppear() {
                player.isMuted = true
                player.play()
            }
        VStack {

Here is a screenshot of the video for aspect ratio reference. Picture an iPhone held upright (portrait) in the center of this screenshot. That's all of the frame I want visible filling the entirety of the screen. screenshot of video

Thank you so much for your help!!


Solution

  • Assuming your video's aspect ratio is 16:9, something like this would work:

    struct ContentView: View {
        private let player = AVPlayer(url: URL(fileURLWithPath: Bundle.main.path(forResource: "mov1", ofType: "mov")!))
        
        var body: some View {
            ZStack {
                GeometryReader { proxy in
                    VideoPlayer(player: player)
                        .ignoresSafeArea()
                        .frame(width: proxy.size.height * 16 / 9, height: proxy.size.height)
                        .position(x: proxy.size.width / 2, y: proxy.size.height / 2)
                        .onAppear() {
                            player.isMuted = true
                            player.play()
                        }
                }
            }
        }
    }
    

    It uses the GeometryReader to get the available size to the View, then translates that to a frame for the VideoPlayer. Finally, it positions it so that it's centered using the position modifier.