Remove padding / spacing between label and content in a disclosure group

59 Views Asked by At

I am creating a disclosure group as follows:

DisclosureGroup(isExpanded: $isShowingAllOpeningHours) {
    Text("Content")
        .frame(maxWidth: .infinity, alignment: .leading)
        .background(.red)
        .padding(.bottom, .zero)
} label: {
    Text("Title")
        .background(.green)
        .padding(.bottom, .zero)
}
.background(.yellow)

I've added the colors just to illustrate the point

This gives me the following the the disclosure group is collapsed

Disclosure group custom SwiftUI

And this when it is expanded

custom Disclosure group expanded SwiftUI

There seems to be some padding around the label in a disclosure group as seen by the yellow background.

Is there a way to remove this padding.

Since this disclosure group is within a scrollview, I've tried adjusting insets but this did not work either.

3

There are 3 best solutions below

0
Benzy Neez On

The extra padding appears to be 4pt at top and bottom. This stays the same even when the text size is increased.

You can eliminate it by applying negative padding of the same amount:

Text("Title")
    .background(.green)
    // .padding(.bottom, .zero)
    .padding(.vertical, -4) // 

Screenshot

Of course, the padding may change in a future iOS release. So you may want to restrict the workaround to versions for which you have tested it.

0
Sweeper On

You can use your own DisclosureGroupStyle. Make it a VStack with 0 spacing. You do need to reinvent the expansion logic

struct NoVerticalPadding: DisclosureGroupStyle {
    func makeBody(configuration: Configuration) -> some View {
        VStack(spacing: 0) {
            Button {
                withAnimation {
                    configuration.isExpanded.toggle()
                }
            } label: {
                HStack {
                    configuration.label
                    Spacer()
                    Image(systemName: configuration.isExpanded ? "chevron.up" : "chevron.forward")
                        .contentTransition(.symbolEffect)
                }
            }
            if configuration.isExpanded {
                configuration.content
                    .transition(.asymmetric(insertion: .push(from: .bottom), removal: .identity))
            }
        }
    }
}

extension DisclosureGroupStyle {
    static var noVerticalPadding: NoVerticalPadding { .init() }
}

At the end of the DisclosureGroup, add

.disclosureGroupStyle(.noVerticalPadding)
0
Jayant Badlani On

Yes, you can remove the padding in DisclosureGroups or easily customize them with your own DisclosureGroupStyle. You can achieve nearly anything you desire.

For example, here I've created one that transitions and looks similar to the default disclosure group style. I hope it helps to resolve your query.

enter image description here

import SwiftUI

struct ContentView2: View {
    
    @State var isShowingAllOpeningHours = true
    
    var body: some View {
        
        DisclosureGroup(isExpanded: $isShowingAllOpeningHours) {
            
            Text("Content")
                .frame(maxWidth: .infinity, alignment: .leading)
                .background(Color.red)
                .padding(.bottom, 0)
        } label: {
            Text("Title")
                .background(Color.green)
        }
        .background(Color.yellow)
        .disclosureGroupStyle(ZeroPaddingDisclosureGroupStyle()) // Apply custom DisclosureGroupStyle
    }
}

#Preview {
    ContentView2()
}

DisclosureGroupStyle Code

struct ZeroPaddingDisclosureGroupStyle: DisclosureGroupStyle {
    
    func makeBody(configuration: Configuration) -> some View {
        VStack {
            Button {
                withAnimation {
                    configuration.isExpanded.toggle()
                }
            } label: {
                VStack(alignment: .leading, spacing: 0) {
                    HStack {
                        configuration.label
                        Spacer()
                        Image(systemName: configuration.isExpanded ? "chevron.down" : "chevron.forward")
                            .contentTransition(.symbolEffect)
                    }
                    
                    if configuration.isExpanded {
                        configuration.content
                            .transition(.asymmetric(insertion: .push(from: .bottom), removal: .identity))
                    }
                }
            }
        }
    }
}