从 url AVPlayer swiftui 加载时显示活动指示器和错误

问题描述 投票:0回答:1

我试图从 URL 加载短视频,我发现最好的方法是使用 AVPlayer,我找到了下面的代码,但它没有显示活动指示器,如果用户没有互联网,它也不会显示播放视频。预先感谢。

import SwiftUI
import AVKit

struct ContentView: View {
    
    @State var player = AVPlayer(url: URL(string: "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ElephantsDream.mp4")!)
    @State var isplaying = false
    @State var showcontrols = false
    @State var value : Float = 0
    
    var body: some View {
        
        VStack{
            
            ZStack{
                
                VideoPlayer(player: $player)
                
                if self.showcontrols{
                    
                    Controls(player: self.$player, isplaying: self.$isplaying, pannel: self.$showcontrols,value: self.$value)
                }
                
            }
            .frame(height: UIScreen.main.bounds.height / 3.5)
            .onTapGesture {
                
                self.showcontrols = true
            }
            
            GeometryReader{_ in
                
                VStack{
                    
                    Text("Custom Video Player").foregroundColor(.white)
                }
            }
        }
        .background(Color.black.edgesIgnoringSafeArea(.all))
        .onAppear {
            
            self.player.play()
            self.isplaying = true
        }
    }
}

这是主屏幕,即ContentView

struct Controls : View {
    
    @Binding var player : AVPlayer
    @Binding var isplaying : Bool
    @Binding var pannel : Bool
    @Binding var value : Float
    
    var body : some View{
        
        VStack{
            Spacer()
            HStack{
                Button(action: {
                    if self.isplaying{
                        
                        self.player.pause()
                        self.isplaying = false
                    }
                    else{
                        self.player.play()
                        self.isplaying = true
                    }
                    if self.player.currentItem?.duration.seconds == self.player.currentTime().seconds{
                        print("did it")
                        self.player.seek(to: CMTime.zero)
                        self.player.play()
                        self.isplaying = true
                    }
                }) {
                    
                    Image(systemName: self.isplaying ? "pause.fill" : "play.fill")
                        .font(.title)
                        .foregroundColor(.white)
                        .padding(20)
                }
                
            }
            
        }.padding()
        .onTapGesture {
            self.pannel = false
        }
    }
    
    func getSliderValue()->Float{
        
        return Float(self.player.currentTime().seconds / (self.player.currentItem?.duration.seconds)!)
    }
    
    func getSeconds()->Double{
        
        return Double(Double(self.value) * (self.player.currentItem?.duration.seconds)!)
    }
}

控制视频的按钮。

class Host : UIHostingController<ContentView>{
    
    override var preferredStatusBarStyle: UIStatusBarStyle{
        
        return .lightContent
    }
}
struct VideoPlayer : UIViewControllerRepresentable {
    
    @Binding var player : AVPlayer
    
    func makeUIViewController(context: UIViewControllerRepresentableContext<VideoPlayer>) -> AVPlayerViewController {
        
        let controller = AVPlayerViewController()
        controller.player = player
        controller.showsPlaybackControls = false
        controller.videoGravity = .resize
        return controller
    }
    
    func updateUIViewController(_ uiViewController: AVPlayerViewController, context: UIViewControllerRepresentableContext<VideoPlayer>) {
        
        
    }
}

ios swift video swiftui avplayer
1个回答
0
投票

带有加载指示器的 SwiftUI 视频播放器

我创建了视频播放器,它提供了一个基于 SwiftUI 的视频播放器组件,其中包含视频加载时的活动指示器。它利用 AVKit 和 AVFoundation 框架创建带有 AVPlayerViewController 和 UIActivityIndicatorView 的自定义 UIView。

代码

这是要点的链接。

import SwiftUI
import AVKit

struct VideoPlayer: UIViewRepresentable {
    var videoURL: URL
    let videoPlayerView = ActivityIndicatorPlayer()
    
    func makeUIView(context: Context) -> ActivityIndicatorPlayer {
        let player = AVPlayer(url: videoURL)
        videoPlayerView.setPlayer(player: player)
        videoPlayerView.startLoading()
        
        player.addObserver(context.coordinator, forKeyPath: "status", options: [.old, .new], context: nil)
        
        return videoPlayerView
    }
    
    func updateUIView(_ uiView: ActivityIndicatorPlayer, context: Context) {}
    
    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }
    
    class Coordinator: NSObject {
        var parent: VideoPlayer
        
        init(_ parent: VideoPlayer) {
            self.parent = parent
        }
        
        override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
            if keyPath == "status", let change = change, let newValue = change[NSKeyValueChangeKey.newKey] as? Int {
                if newValue == AVPlayer.Status.readyToPlay.rawValue {
                    parent.videoPlayerView.stopLoading()
                    
                }
            }
        }
    }
}

class ActivityIndicatorPlayer: UIView {
    private let playerViewController = AVPlayerViewController()
    private let activityIndicator = UIActivityIndicatorView(style: .large)
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        configurePlayerView()
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        configurePlayerView()
    }
    
    private func configurePlayerView() {
        addSubview(playerViewController.view)
        addSubview(activityIndicator)
        
        playerViewController.view.translatesAutoresizingMaskIntoConstraints = false
        activityIndicator.translatesAutoresizingMaskIntoConstraints = false
        
        NSLayoutConstraint.activate([
            playerViewController.view.topAnchor.constraint(equalTo: topAnchor),
            playerViewController.view.leadingAnchor.constraint(equalTo: leadingAnchor),
            playerViewController.view.trailingAnchor.constraint(equalTo: trailingAnchor),
            playerViewController.view.bottomAnchor.constraint(equalTo: bottomAnchor),
            
            activityIndicator.centerXAnchor.constraint(equalTo: centerXAnchor),
            activityIndicator.centerYAnchor.constraint(equalTo: centerYAnchor)
        ])
    }
    
    func setPlayer(player: AVPlayer?) {
        playerViewController.player = player
    }
    
    func startLoading() {
        activityIndicator.startAnimating()
    }
    
    func stopLoading() {
        activityIndicator.stopAnimating()
    }
}




© www.soinside.com 2019 - 2024. All rights reserved.