要更改TabBar背景和其他属性,大约有两种处理方法。
- 通过包含TabView的视图的init(((请参见:https://stackoverflow.com/a/56971573/2192483)
- 通过TabView上的.onPear(((请参见:https://stackoverflow.com/a/63414605/2192483-感谢@Asperi;请参阅:https://schwiftyui.com/swiftui/customizing-your-tabviews-bar-in-swiftui/-感谢@Dan O'Leary(
这些解决方案在视图加载和通过触摸选项卡重新加载选项卡栏时都很有效。
但是,如果您想通过@Published值中定义的属性的常规方式以编程方式更改TabBar属性,而无需在TabBar按钮上进行用户交互。这不起作用,因为无论是init((还是.onAppear((,这两个方法都不是prop的订阅者。以便嵌入TabView的视图不会重新加载。
我终于找到了一种方法,用常规的@Published属性触发TabView重载,而不是从用户的选项卡按钮触摸。
以下是一个基于应用程序的示例,该应用程序具有允许更改应用程序外观的设置面板,包括TabBar背景色。
1(Main结构嵌入了嵌入TabView的ContentView
•设置模型嵌入共享的属性a(皮肤值b(触发重新加载的标志
•ContentView拥有一个参数:skinChanged
@main
struct MyApp: App {
@ObservedObject private var settings = SettingsModel.shared
var body: some Scene {
WindowGroup {
ContentView(skinChanged: settings.skinChanged)
}
}
}
2(ContentView结构嵌入TabView
•init(skinChanged:Bol(允许自定义TabBar外观如果settings.skin更改值,将重新加载
•init/if!skinChanged{}仅在需要时应用TabBar外观
•身体/如果!self.settings.skinChanged{}允许在从TabView到矩形(作为背景(的交替视图
struct ContentView: View {
@ObservedObject private var settings = SettingsModel.shared
init(skinChanged: Bool) {
if !skinChanged {
let tabBarAppearance = UITabBar.appearance()
tabBarAppearance.backgroundColor = UIColor(settings.skin.tabBarBg)
tabBarAppearance.unselectedItemTintColor = UIColor(settings.skin.tabBarUnselected)
}
}
var body: some View {
if !self.settings.skinChanged {
TabView(selection: $someStateProp) {
...
}
} else {
Rectangle()
.fill(settings.skin.tabBarBg)
}
}
}
3(SettingModel结构发布触发外观更改和外观值的属性
•为了在ContentView(skinChanged:(中创建更改settings.skinChanged,值必须从false传递到true,然后返回错误
•要让UI应用每个更改,必须有2个更改与2个同步任务并行
class SettingsModel: ObservableObject {
static public let shared = SettingsModel()
...
@Published var skin = Skin(style: .modern)
@Published var skinId = 0 {
didSet {
...
self.skin = Skin(style: Skin.Style.allCases[self.skinId])
DispatchQueue.main.asyncAfter(deadline: .now()) {
self.skinChanged = true
}
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
self.skinChanged = false
}
}
}
@Published var skinChanged = false
...
}