SwiftUI中iOS16+全屏VideoPlayer关闭按钮缺失问题求助
iOS16下fullScreenCover中VideoPlayer无关闭按钮的解决办法
问题原因
iOS16对fullScreenCover的默认导航栏行为做了调整:当内部视图使用ignoresSafeArea()时,系统不再自动生成左上角的关闭按钮,而iOS15及以下版本会保留这个按钮。
解决方法
方法1:用Navigation组件手动添加系统风格按钮
通过给VideoPlayerView添加导航容器,手动在工具栏中放置关闭按钮,同时绑定父视图的isPresented状态来控制弹窗关闭。
- 修改
VideoPlayerView,新增绑定属性并包裹导航容器:
struct VideoPlayerView: View { @StateObject var model: VideoPlayerViewModel let video: VideoModel @Binding var isPresented: Bool // 新增绑定,用于控制弹窗关闭 init(video: VideoModel, isPresented: Binding<Bool>) { self._model = StateObject(wrappedValue: VideoPlayerViewModel(video: video)) self.video = video self._isPresented = isPresented } var body: some View { // iOS16+用NavigationStack,兼容iOS15可替换为NavigationView NavigationStack { if let player = model.player { VideoPlayer(player: player) .ignoresSafeArea() .toolbar { ToolbarItem(placement: .navigationBarLeading) { Button("关闭") { isPresented = false } } } } } } }
- 父视图中传递
isPresented绑定:
.fullScreenCover( isPresented: $showVideoSheet, onDismiss: { selectedVideo = nil }, content: { if let video = selectedVideo { VideoPlayerView(video: video, isPresented: $showVideoSheet) } } )
方法2:自定义悬浮关闭按钮
如果不想依赖导航组件,可以直接在视频视图上叠加一个自定义关闭按钮,样式可自由调整,不受系统版本影响。
修改VideoPlayerView的body(需先添加@Binding var isPresented: Bool属性并在父视图传递绑定):
var body: some View { ZStack { if let player = model.player { VideoPlayer(player: player) .ignoresSafeArea() } // 叠加自定义关闭按钮 VStack(alignment: .leading) { Button(action: { isPresented = false }) { Image(systemName: "xmark") .foregroundColor(.white) .padding(8) .background(Color.black.opacity(0.6)) .clipShape(Circle()) } Spacer() } .padding(.top, 40) .padding(.leading, 16) } }
总结
两种方法都能解决iOS16的关闭按钮缺失问题:方法1贴合系统原生风格,方法2自由度更高,可自定义按钮样式和位置。
内容的提问来源于stack exchange,提问作者Jaidyn Belbin
相关产品推荐
相关产品推荐

