SwiftUI:如何在TabView中切换选中/未选中状态的填充/线框图标
问题原因
SwiftUI 的 tabItem 内容属于静态渲染配置,初始化时会被转换为底层 UITabBarItem 的固定配置,不会响应内部的 @State 状态变化。你在 tabItem 闭包中写的选中状态判断逻辑只会在页面首次加载时执行一次,后续状态变更不会触发 tabItem 内容更新,因此始终显示首次渲染的填充样式图标。
解决方案
方案1:使用系统默认SF Symbol适配规则(推荐)
iOS 系统对 TabBar 中使用的 SF Symbol 有默认适配逻辑:只要你传入线框版本的 SF Symbol 名称,系统会自动在标签选中时切换为对应的填充样式,无需手动判断状态。
修改后的代码如下:
struct ListTabView: View { @State private var selectedTab = 0 var body: some View { NavigationView { TabView(selection: $selectedTab) { Text("Tab 1") .onTapGesture { self.selectedTab += 1 } .tabItem { Image(systemName: "star") Text("First") } .tag(0) Text("Tab 2") .onTapGesture { self.selectedTab -= 1 } .tabItem { Image(systemName: "moon.stars") Text("Second") } .tag(1) } .accentColor(.pink) .onAppear { UITabBar.appearance().barTintColor = .white } } } }
方案2:强制TabView重绘(适用于自定义图标场景)
如果你使用的是自定义图标,没有对应配对的 SF Symbol 可以依赖系统自动切换,可以给 TabView 绑定和选中状态关联的 id,让选中状态变化时强制重绘整个 TabView,触发 tabItem 的逻辑重新执行:
TabView(selection: $selectedTab) { // 原有Tab内容保持不变 } .id(selectedTab) // 新增该行即可
注意:该方案会在每次切换标签时重绘整个 TabView 及其内部所有子视图,标签内容复杂时可能产生性能损耗,非必要场景不推荐使用。
内容的提问来源于stack exchange,提问作者Hamad Fuad
相关产品推荐
相关产品推荐

