SwiftUI中应用toolbarColorScheme后底部工具栏项布局为何异常?
SwiftUI底部工具栏布局异常问题修复
问题现象
默认状态下,当底部工具栏包含2个以上ToolbarItem时,除最后一项居右外,其余所有项均居左。但在应用.toolbarColorScheme(.light, for: .bottomBar)或.toolbarColorScheme(.dark, for: .bottomBar)修饰符后,滚动至页面最底部时,第二项也会移动到右侧,导致布局错乱。
复现代码
// // ToolbarGlitchDemo.swift // ToolbarGlitchDemo // // Created by rayhaanlykhan on 15/04/2024. // import SwiftUI struct ToolbarGlitchDemo: View { var body: some View { NavigationStack { ZStack { Color.gray.ignoresSafeArea() ScrollView { ForEach(0..<15) { _ in Rectangle() .fill(.blue) .frame(width: 200, height: 200) .frame(maxWidth: .infinity) } } } .navigationTitle("Toolbar Glitch Demo") .toolbar { ToolbarItem(placement: .bottomBar) { // center HStack { Image(systemName: "scribble") Image(systemName: "gear") } .background(.yellow) } ToolbarItem(placement: .bottomBar) { HStack { Image(systemName: "person.fill") } .background(.red) } ToolbarItem(placement: .bottomBar) { HStack { Image(systemName: "person") Image(systemName: "person") } .background(.green) } } .toolbarColorScheme(.light, for: .bottomBar) } } } #Preview { ToolbarGlitchDemo() }
解决方案
这属于SwiftUI的系统布局bug,可通过以下两种方式修复:
方法1:用ToolbarItemGroup明确分组控制位置
将需要居左的项统一放在.bottomBarLeading分组,居右项放在.bottomBarTrailing分组,强制固定布局逻辑:
.toolbar { // 左部项分组 ToolbarItemGroup(placement: .bottomBarLeading) { HStack { Image(systemName: "scribble") Image(systemName: "gear") } .background(.yellow) HStack { Image(systemName: "person.fill") } .background(.red) } // 右部项分组 ToolbarItemGroup(placement: .bottomBarTrailing) { HStack { Image(systemName: "person") Image(systemName: "person") } .background(.green) } } .toolbarColorScheme(.light, for: .bottomBar)
方法2:自定义底部工具栏替代系统Toolbar
如果系统Toolbar的bug难以规避,可直接用自定义视图实现底部栏,完全掌控布局:
NavigationStack { ZStack { Color.gray.ignoresSafeArea() ScrollView { ForEach(0..<15) { _ in Rectangle() .fill(.blue) .frame(width: 200, height: 200) .frame(maxWidth: .infinity) } } // 添加自定义底部栏 .safeAreaInset(edge: .bottom) { HStack { // 左部内容 HStack(spacing: 16) { HStack { Image(systemName: "scribble") Image(systemName: "gear") } .background(.yellow) HStack { Image(systemName: "person.fill") } .background(.red) } Spacer() // 右部内容 HStack { Image(systemName: "person") Image(systemName: "person") } .background(.green) } .padding(.horizontal) .frame(height: 44) .background(.white) // 匹配light配色 } } .navigationTitle("Toolbar Glitch Demo") }
说明
ToolbarItemGroup的方式更贴合系统Toolbar的原生交互,自定义底部栏则提供了完全自由的布局控制,可根据需求选择。
内容的提问来源于stack exchange,提问作者Rehan Ali Khan
相关产品推荐
相关产品推荐

