SwiftUI - 如何将当前的强调色传递给工作表?

Posted

技术标签:

【中文标题】SwiftUI - 如何将当前的强调色传递给工作表?【英文标题】:SwiftUI - How can I pass the current accent color to a sheet? 【发布时间】:2021-05-29 22:48:00 【问题描述】:

到目前为止,SwiftUI 不会将当前的强调色传递给工作表。在以下示例中,工作表中按钮的强调色不会是红色。

// Some parent view which sets an accent color, can't change this
struct ContentView: View 
    var body: some View 
        ChildView()
            .accentColor(.red)
    


// A child view that uses the accent color set by the parent
struct ChildView: View 
    @State var showSheet = false
    
    var body: some View 
        VStack 
            Button("this uses red")
                showSheet = true
            
            .sheet(isPresented: $showSheet)
                VStack 
                    Button("this will ignore accent color") 
                
            
        
    

我猜这是一个错误,但我正在寻找解决方法。问题是,我不能只设置.accentColor(.red) 或呈现的表格内的任何内容,因为我的应用程序根据设置使用动态强调色。也就是说——我需要能够将 ChildView 的 accentColor 传递到工作表上,而不必知道它是什么。

我尝试将.accentColor(.accentColor) 传递给工作表中的视图,但不起作用。

有什么想法吗?

【问题讨论】:

如果你把.accentColor(.red)放在VStack上,它应该可以工作 正如问题中所述,我不能这样做,因为我正在为整个应用程序动态设置强调色,并且需要尊重设置。 不幸的是,通过.sheet 呈现视图不会继承环境。有人说这是一个 bug,但在 SwiftUI 2.0 之前就一直是这样,现在仍然存在。另一个问题是某些内置环境设置,例如 accentColor 使用的设置,不是公开的,因此您无法访问它们并传递它们。 【参考方案1】:

有很多方法可以做到这一点,以下只是一种方法:

(macos 11.4、xcode 12.5、目标 ios 14.5 和 macCatalyst 11.3。)

struct ContentView: View 
    @State var showSheet = false
    @State var accentColor = Color.red
    
    var body: some View 
        VStack 
            Button("this uses red")
                showSheet = true
            .sheet(isPresented: $showSheet)
                TheSheetView(accentColor: $accentColor)
            
        .accentColor(accentColor)
    

struct TheSheetView: View 
    @Binding var accentColor: Color
    var body: some View 
        VStack 
            Button("this will not ignore accent color") .accentColor(accentColor)
        
    

或者你可以试试这个:

@main
struct TestErrorApp: App 
    var myAccent = MyAccent()
    var body: some Scene 
        WindowGroup 
            ContentView().environmentObject(myAccent)
        
    


class MyAccent: ObservableObject 
    @Published var color = Color.red


struct ContentView: View 
    @EnvironmentObject var myAccent: MyAccent  // <--- will be available to all child views
    @State var showSheet = false
    
    var body: some View 
        VStack 
            Button("this uses red")
                showSheet = true
            .sheet(isPresented: $showSheet)
                TheSheetView().environmentObject(myAccent) // <--- need this for sheets
            
        .accentColor(myAccent.color)
    

struct TheSheetView: View 
    @EnvironmentObject var myAccent: MyAccent
    var body: some View 
        VStack 
            Button("this will ignore accent color") .accentColor(myAccent.color)
        
    

【讨论】:

这不起作用。强调色通过环境传递到 .accentColor 修饰符的任何子视图——我需要一种从环境中获取该值的方法。通常,访问 Color.accentColor 会返回当前环境的强调色,但这在工作表修饰符中不起作用。 向我们展示您正在使用的代码,而不是不具有代表性的示例。 我无法显示确切的代码,因为它是专有的。但是,我的示例+描述完全代表了我的问题。我已对其进行了更新以使其更清晰。

以上是关于SwiftUI - 如何将当前的强调色传递给工作表?的主要内容,如果未能解决你的问题,请参考以下文章

如何正确地将“单元格项目”从 SwiftUI LazyVGrid 传递给 .sheet?

如何使用 SwiftUI 将变量传递给 MFMailComposeViewController()?

在 SwiftUI 中,如何将primaryAction ToolbarItem 加粗?

如何使用 SwiftUI 更改主题颜色?

SwiftUI - 将 fetchResult 传递给另一个视图

如何将通用视图传递给 SwiftUI 中的结构