SwiftUI iPad自定义视频播放器:仅保留全屏按钮隐藏其余控件
自定义SwiftUI iPad视频播放器:仅保留全屏按钮
要实现隐藏原生所有控件、仅保留自定义全屏按钮的视频播放器,我们可以通过隐藏原生播放控件+添加自定义全屏按钮+实现全屏切换逻辑来完成,以下是完整的实现方案:
步骤1:修改自定义视频播放器(支持全屏状态绑定)
给CustomVideoPlayer添加状态绑定,实现SwiftUI与UIKit的状态同步,同时优化通知监听的生命周期避免内存泄漏:
import SwiftUI import AVKit struct CustomVideoPlayer: UIViewControllerRepresentable { var player: AVPlayer @Binding var isFullScreen: Bool private let playerObserver = PlayerObserver() func makeUIViewController(context: Context) -> AVPlayerViewController { let controller = AVPlayerViewController() controller.player = player controller.showsPlaybackControls = false controller.videoGravity = .resizeAspectFill // 绑定全屏状态回调 context.coordinator.controller = controller context.coordinator.isFullScreen = $isFullScreen // 设置循环播放 playerObserver.startObserving(player: player) return controller } func updateUIViewController(_ uiViewController: AVPlayerViewController, context: Context) { // 根据绑定状态切换全屏 if isFullScreen { uiViewController.enterFullScreen(animated: true) } else { uiViewController.exitFullScreen(animated: true) } } func makeCoordinator() -> Coordinator { Coordinator() } // 协调UIKit与SwiftUI的状态交互 class Coordinator: NSObject { weak var controller: AVPlayerViewController? var isFullScreen: Binding<Bool>? @objc func handleFullScreenChange(_ notification: Notification) { guard let controller = controller, let isFullScreen = isFullScreen else { return } DispatchQueue.main.async { isFullScreen.wrappedValue = controller.isFullScreen } } } // 封装循环播放的通知监听,避免内存泄漏 class PlayerObserver: NSObject { private var observer: NSObjectProtocol? func startObserving(player: AVPlayer) { observer = NotificationCenter.default.addObserver( forName: .AVPlayerItemDidPlayToEndTime, object: player.currentItem, queue: .main ) { [weak self] _ in guard let self = self else { return } player.seek(to: .zero) player.play() } } deinit { if let observer = observer { NotificationCenter.default.removeObserver(observer) } } } }
步骤2:在ContentView中添加自定义全屏按钮
通过ZStack将自定义全屏按钮叠加在视频播放器上层,点击时切换全屏状态:
import SwiftUI import AVKit struct ContentView: View { private let player1 = AVPlayer(url: URL(string: "urlPlaceholder")!) @State private var isFullScreen = false var body: some View { ZStack { CustomVideoPlayer(player: player1, isFullScreen: $isFullScreen) .onAppear { player1.play() } // 自定义全屏按钮,固定在右下角 Button(action: { isFullScreen.toggle() }) { 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.5)) .cornerRadius(8) } .padding(.bottom, 20) .padding(.trailing, 20) .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .bottomTrailing) .opacity(isFullScreen ? 0 : 1) // 全屏时隐藏按钮,退出时显示 } .edgesIgnoringSafeArea(isFullScreen ? .all : .none) } }
关键说明
- 状态双向绑定:通过
@Binding实现SwiftUI的isFullScreen状态与UIKit播放器的全屏状态同步,确保交互一致性。 - 生命周期管理:将循环播放的通知监听封装到独立类中,在对象销毁时自动移除监听,避免内存泄漏。
- 系统级全屏切换:利用
AVPlayerViewController的原生全屏方法实现系统级的全屏体验,无需手动调整视图布局。 - 自定义按钮交互:根据全屏状态切换按钮图标,全屏时自动隐藏按钮,符合用户操作习惯。
内容的提问来源于stack exchange,提问作者William Bruijntjes
相关产品推荐
相关产品推荐

