SwiftUI实现视频播放器自定义全屏按钮方案
实现带自定义全屏按钮的视频播放器
针对你的需求,我们可以通过添加状态变量跟踪全屏状态、叠加自定义控件层,同时调整播放器布局与视频重力的方式实现自定义全屏功能。以下是修改后的完整代码:
struct HustleVideoPlayerR: View { let url: URL @State var player = AVPlayer(url: URL(string: "https://www.google.com")!) @State var viewID = false @State var aspect: CGSize = CGSize(width: 16, height: 9) // 新增:跟踪全屏状态 @State private var isFullScreen = false // 新增:控制自定义控件显示/隐藏 @State private var showCustomControls = true var body: some View { ZStack { // 核心播放器 VideoPlayer(player: $player, showControls: false, isFullScreen: $isFullScreen) .id(viewID) .aspectRatio(isFullScreen ? .fill : aspect, contentMode: isFullScreen ? .fill : .fit) .background(Color.black) .edgesIgnoringSafeArea(isFullScreen ? .all : []) .onTapGesture { withAnimation { showCustomControls.toggle() } } // 自定义全屏控件层 if showCustomControls { VStack { Spacer() HStack { Spacer() Button(action: toggleFullScreen) { Image(systemName: isFullScreen ? "arrow.down.right.and.arrow.up.left" : "arrow.up.left.and.arrow.down.right") .foregroundColor(.white) .padding() .background(Color.black.opacity(0.7)) .cornerRadius(8) } .padding(.trailing, 16) .padding(.bottom, 16) } } .transition(.opacity) } } .onAppear { player = AVPlayer(url: url) viewID.toggle() Task { do { if let final = try await getVideoResolution(url: url.absoluteString) { self.aspect = final } } catch { } } } .onDisappear { player.pause() player = AVPlayer(url: URL(string: "https://www.google.com")!) viewID.toggle() // 页面消失时强制退出全屏 if isFullScreen { toggleFullScreen() } } } // 全屏切换逻辑 private func toggleFullScreen() { isFullScreen.toggle() // 可选:锁定/恢复屏幕方向 if isFullScreen { UIDevice.current.setValue(UIInterfaceOrientation.landscapeLeft.rawValue, forKey: "orientation") UIApplication.shared.isStatusBarHidden = true } else { UIDevice.current.setValue(UIInterfaceOrientation.portrait.rawValue, forKey: "orientation") UIApplication.shared.isStatusBarHidden = false } } } // 修改后的播放器容器,支持全屏状态绑定 struct VideoPlayer : UIViewControllerRepresentable { @Binding var player : AVPlayer let showControls: Bool @Binding var isFullScreen: Bool func makeUIViewController(context: UIViewControllerRepresentableContext<VideoPlayer>) -> AVPlayerViewController { let controller = AVPlayerViewController() controller.player = player controller.showsPlaybackControls = showControls controller.allowsVideoFrameAnalysis = false return controller } func updateUIViewController(_ uiViewController: AVPlayerViewController, context: UIViewControllerRepresentableContext<VideoPlayer>) { // 根据全屏状态调整视频填充模式 uiViewController.videoGravity = isFullScreen ? .resizeAspectFill : .resizeAspect } } // 假设你已实现的视频分辨率获取函数 func getVideoResolution(url: String) async throws -> CGSize? { // 你的具体实现逻辑 return CGSize(width: 16, height: 9) }
关键实现说明
- 全屏状态控制:通过
isFullScreen变量切换播放器的布局模式,全屏时忽略安全区、使用填充模式占满屏幕,非全屏时保持视频原始比例。 - 自定义控件叠加:用ZStack将全屏按钮放在播放器上层,点击播放器可切换控件显示状态(可根据需求调整显示逻辑)。
- 视频重力适配:在
updateUIViewController中根据全屏状态切换视频填充模式,确保全屏时视频铺满屏幕,非全屏时保持比例。 - 生命周期处理:页面消失时强制退出全屏,避免返回后残留全屏状态。
注意事项
- 嵌套在ScrollView中时,全屏状态下播放器会自动覆盖ScrollView的其他内容,无需额外处理层级。
- 屏幕方向锁定需要在项目
Info.plist中添加对应支持的方向,或者在父ViewController中重写supportedInterfaceOrientations方法。 - 可根据需求扩展自定义控件,比如添加播放/暂停按钮、进度条等。
内容的提问来源于stack exchange,提问作者Ahmed Zaidan
相关产品推荐
相关产品推荐

