iOS 16中SwiftUI Menu异常行为的解决方案求助
问题场景
以下SwiftUI代码在iOS 15上运行正常,但在iOS 16设备中,当键盘弹出时,底部的Menu会出现帧异常、错位的问题,点击Menu后情况更严重。尝试过添加.fixedSize()等常见方案,均无效。
@State private var textInput = "" var body: some View { VStack { TextEditor(text: $textInput) .padding() .border(.blue, width: 1) HStack { Button("Bottom button") { print("Button pressed") } .padding() .border(.green, width: 1) Spacer() Menu("Bottom Menu") { Button("Menu option 1") { print("Option 1 pressed") } Button("Menu option 2") { print("Option 2 pressed") } } .padding() .border(.red, width: 1) } .background(.gray) } }
左侧为iOS 16异常表现,右侧为iOS 15正常表现:
可行解决办法
方案一:将底部操作栏移入Toolbar(推荐)
利用系统Toolbar的原生布局逻辑,让底部组件自动适配键盘弹出场景,从根源避免布局错乱:
@State private var textInput = "" var body: some View { NavigationStack { TextEditor(text: $textInput) .padding() .border(.blue, width: 1) .toolbar { ToolbarItem(placement: .bottomBar) { HStack { Button("Bottom button") { print("Button pressed") } .padding() .border(.green, width: 1) Spacer() Menu("Bottom Menu") { Button("Menu option 1") { print("Option 1 pressed") } Button("Menu option 2") { print("Option 2 pressed") } } .padding() .border(.red, width: 1) } .background(.gray) } } } }
方案二:给Menu设置固定尺寸
通过固定Menu的宽高,强制布局系统保持其尺寸稳定,避免键盘弹出时的布局重计算错误:
@State private var textInput = "" var body: some View { VStack { TextEditor(text: $textInput) .padding() .border(.blue, width: 1) HStack { Button("Bottom button") { print("Button pressed") } .padding() .border(.green, width: 1) Spacer() Menu("Bottom Menu") { Button("Menu option 1") { print("Option 1 pressed") } Button("Menu option 2") { print("Option 2 pressed") } } .padding() .border(.red, width: 1) .frame(width: 120, height: 44) // 根据实际需求调整尺寸 } .background(.gray) } }
方案三:动态记录Menu原始尺寸
通过GeometryReader在视图加载时记录Menu的原始尺寸,后续强制使用该尺寸,适配动态布局场景:
@State private var textInput = "" @State private var menuSize: CGSize = .zero var body: some View { VStack { TextEditor(text: $textInput) .padding() .border(.blue, width: 1) HStack { Button("Bottom button") { print("Button pressed") } .padding() .border(.green, width: 1) Spacer() Menu("Bottom Menu") { Button("Menu option 1") { print("Option 1 pressed") } Button("Menu option 2") { print("Option 2 pressed") } } .padding() .border(.red, width: 1) .background( GeometryReader { proxy in Color.clear .onAppear { menuSize = proxy.size } } ) .frame(width: menuSize.width, height: menuSize.height) } .background(.gray) } }
内容的提问来源于stack exchange,提问作者TheQ
相关产品推荐
相关产品推荐

