9

How can I change the default gray background color of a GroupBox view in SwiftUI?

I tried adding a background modifier, but this just changes the white background underneath the box (see screenshot).

GroupBox(label: Text("Label"), content: {
    Text("Content")
})
.background(Color.blue)

SwiftUI GroupBox screencapture with gray background and blue corners

JacobF
  • 2,305
  • 3
  • 24
  • 36
  • I don't think there is a way now but this might help you: https://www.facebook.com/349275022095690/posts/someone-asked-me-earlier-if-we-can-change-the-groupbox-background-color-in-swift/1141734002849784/ – Ludyem Oct 09 '20 at 12:05

4 Answers4

12

This is default group box style. You can create whatever group box needed using custom style.

Here is an example. Tested with Xcode 12 / iOS 14.

demo

struct DemoGroupBox: View {
    var body: some View {
        GroupBox(label: Text("Label"), content: {
             Text("Content")
        })
        .groupBoxStyle(TransparentGroupBox())
        .padding()
    }
}

struct TransparentGroupBox: GroupBoxStyle {
    func makeBody(configuration: Configuration) -> some View {
        configuration.content
            .frame(maxWidth: .infinity)
            .padding()
            .background(RoundedRectangle(cornerRadius: 8).fill(Color.blue))
            .overlay(configuration.label.padding(.leading, 4), alignment: .topLeading)
    }
}
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
Asperi
  • 228,894
  • 20
  • 464
  • 690
  • 2
    This is useful, but I don't think it counts as "the answer", because you have to lay out the label yourself. Add in a, "you can't" at the beginning, and then it will be the real answer. –  Oct 11 '20 at 07:20
3

Short answer: it is currently not properly supported by SwiftUI :(

Longer answer: you can create a custom GroupBoxStyle (see example) which will allow you to change the background... but at the cost of having to then manually layout the contents (which somewhat defeats the purpose).

Nathaniel
  • 836
  • 9
  • 19
  • Are you saying the other two answers, which have been validated by the community, are incorrect? If so, why don't they satisfy the requirements? – Jeremy Caney Feb 27 '22 at 02:05
  • 1
    @JeremyCaney I wanted to make it clear to anyone looking for the solution 'at a glance' that it is not possible to simply change the background color. The proposed 'solutions' change the background color - yes - but force you to have to set the corner radius, label layout... making it much more efficient (less lines of code) to simply make a custom component as it is really no longer a standard SwiftUI component. – Nathaniel Feb 28 '22 at 06:37
  • 1
    Example: `VStack() { Text("Label").frame(maxWidth: .infinity, alignment: .leading).padding(.leading, 8) Text("Label") }.padding().background(Color.blue).cornerRadius(15)` – Nathaniel Feb 28 '22 at 06:40
  • 1
    Please [edit] that information into your answer. "It's not possible" by itself is just a comment without an explanation. – General Grievance Mar 02 '22 at 13:49
3

This problem can be solved in this way

Tested on iOS 16, Xcode 14.0 Beta

struct TestView: View {
    var body: some View {
        GroupBox(label: Text("Label"), content: {
            Text("Content")
        })
        .groupBoxStyle(ColoredGroupBox())
        .padding()
    }
}

struct ColoredGroupBox: GroupBoxStyle {
    func makeBody(configuration: Configuration) -> some View {
        VStack {
            HStack {
                configuration.label
                    .font(.headline)
                Spacer()
            }
            
            configuration.content
        }
        .padding()
        .background(RoundedRectangle(cornerRadius: 8, style: .continuous)
            .fill(.blue)) // Set your color here!!
    }
}

Result: enter image description here

Full code for above result

struct TestView: View {
    var body: some View {
        VStack {
            Divider()

            HStack {
                Text("Asperi's solution")
                Text("(Problematic with label)")
                    .bold()
            }
            
            GroupBox(label: Text("Label"), content: {
                Text("Content")
            })
            .groupBoxStyle(TransparentGroupBox())
            .padding()
            
            Divider()
            
            Text("My Solution")
            GroupBox(label: Text("Label"), content: {
                Text("Content")
            })
            .groupBoxStyle(ColoredGroupBox())
            .padding()
            
            Divider()
            
            Text("Default")
            GroupBox(label: Text("Label"), content: {
                Text("Content")
            })
            .padding()
            Divider()
        }
    }
}

struct TransparentGroupBox: GroupBoxStyle {
    func makeBody(configuration: Configuration) -> some View {
        configuration.content
            .frame(maxWidth: .infinity)
            .padding()
            .background(RoundedRectangle(cornerRadius: 8).fill(Color.blue))
            .overlay(configuration.label.padding(.leading, 4), alignment: .topLeading)
    }
}

struct ColoredGroupBox: GroupBoxStyle {
    func makeBody(configuration: Configuration) -> some View {
        VStack {
            HStack {
                configuration.label
                    .font(.headline)
                Spacer()
            }
            
            configuration.content
        }
        .padding()
        .background(RoundedRectangle(cornerRadius: 8, style: .continuous)
            .fill(.blue)) // Set your color here!!
    }
}
Jeremy Caney
  • 7,102
  • 69
  • 48
  • 77
Will
  • 31
  • 1
2

The answer to this question has changed in recent (iOS16) versions. You can now use backgroundStyle(_:). The documentation can be found here

GroupBox(label: Text("Label"), content: {
    Text("Content")
})
.backgroundStyle(Color.blue)
iain
  • 1,693
  • 13
  • 19