如何解决iOS 26中SwiftUI菜单的新行为异常问题
1. 是否必须使用新的气泡及动画样式?
不需要。Xcode 16(对应iOS 18)默认启用了新的.bubble Menu样式,但你可以通过显式指定旧样式来回退到之前的表现:
- 恢复无边框的旧按钮样式:给Menu添加
.menuStyle(.borderlessButton) - 恢复带边框的旧按钮样式:给Menu添加
.menuStyle(.button)
示例代码片段:
Menu { // 菜单选项内容 } label: { // 标签内容 } .menuStyle(.borderlessButton) // 回退到旧样式
2. 保留新样式时解决标签卡顿问题
卡顿的核心原因是菜单打开/关闭时标签布局发生突变,导致重绘动画卡顿。可以通过以下方式优化:
方法一:固定标签布局尺寸
给Menu的标签视图添加固定尺寸约束,确保打开关闭时布局不会跳变:
Menu { ForEach(sortItems, id: \.self) { item in Button(action: { sortedBy = item }) { HStack { Text(item) if item == sortedBy { Image(systemName: "checkmark") } } } } } label: { HStack(spacing: 12) { Image(systemName: "arrow.up.arrow.down") .resizable() .frame(width: 8, height: 12) Text(sortedBy) } .fixedSize(horizontal: true, vertical: false) // 固定水平布局 .frame(minWidth: 130) // 可选:设置最小宽度,避免标签过窄 }
方法二:禁用标签切换动画
如果布局优化后仍有卡顿,可以直接关闭菜单切换时的标签动画:
Menu { // 菜单选项内容 } label: { // 标签内容 } .transaction { $0.animation = nil } // 移除标签动画
额外优化:给选中项添加标记
在菜单选项中添加选中标记,既提升交互体验,也能减少用户对标签状态切换的注意力,间接缓解卡顿感知:
Button(action: { sortedBy = item }) { HStack { Text(item) if item == sortedBy { Image(systemName: "checkmark") .foregroundColor(.accentColor) } } }
完整优化后的代码:
import SwiftUI struct TestView: View { let sortItems = ["Date ajout", "Date de sortie", "Ma note", "Date de visualisation"] @State private var sortedBy: String = "Date ajout" var body: some View { HStack(spacing: 12) { Menu { ForEach(sortItems, id: \.self) { item in Button(action: { sortedBy = item }) { HStack { Text(item) if item == sortedBy { Image(systemName: "checkmark") .foregroundColor(.accentColor) } } } } } label: { HStack(spacing: 12) { Image(systemName: "arrow.up.arrow.down") .resizable() .frame(width: 8, height: 12) Text(sortedBy) } .fixedSize(horizontal: true, vertical: false) .frame(minWidth: 130) } .transaction { $0.animation = nil } Spacer() } .padding(10) .frame(maxWidth: .infinity) .background(.ultraThinMaterial, in: Capsule()) } }
内容的提问来源于stack exchange,提问作者Eric
相关产品推荐
相关产品推荐

