Aligning toggles in a SwiftUI View

297 Views Asked by At

I have this code that contains the labels and toggles shown in the screenshot below

 VStack(alignment: .leading) {
            HStack() {
                Text("Autostart:")
                    .font(.custom("SFProText-Medium", size: 12))
                
                Toggle("Launch on Login", isOn: $launchAtLogin).onChange(of: launchAtLogin) { newValue in
                    LaunchAtLogin.isEnabled = newValue
                    
                    if !isLoginItem() {
                        updateUserDefaults(key: "LaunchOnLogin", value: LaunchAtLogin.isEnabled)
                    }
                }.font(.custom("SFProText-Medium", size: 12))
            }
            .padding(.top, 10)
            .padding(.bottom, 10)
            
            HStack() {
                Text("Updates:")
                    .font(.custom("SFProText-Medium", size: 12))
                Toggle("Allow Automatic Updates", isOn: $allowAutomaticUpdates).onChange(of: allowAutomaticUpdates) { newValue in
                    allowAutomaticUpdates = newValue
                    updateUserDefaults(key: "AllowsAutomaticUpdates", value: allowAutomaticUpdates)
                }.font(.custom("SFProText-Medium", size: 12))
            }
        }
        .padding(.top, 10)
        .padding(.bottom, 10)

enter image description here

I'm trying to figure out how to get the two toggles to always be vertically aligned. I tried manually setting the frame size of them, as well wrapping them inside of another VStack, but none of that has seemed to work

1

There are 1 best solutions below

0
On BEST ANSWER

One way to handle this is to define a custom horizontal alignment guide as follows:

extension HorizontalAlignment {
    enum CustomAlignment: AlignmentID {
        static func defaultValue(in context: ViewDimensions) -> CGFloat {
            context[HorizontalAlignment.center]
        }
    }
    
    static let custom = HorizontalAlignment(CustomAlignment.self)
}

Then use this as the alignment parameter for the outer VStack. To align trailing edges of the Text labels within the HStacks use the modifier

.alignmentGuide(.custom) { d in d[HorizontalAlignment.trailing] }

Putting this all together…

VStack(alignment: .custom) {
    HStack() {
        Text("Autostart:")
            .alignmentGuide(.custom) { d in d[HorizontalAlignment.trailing] }

        Toggle("Launch on Login", isOn: $launchAtLogin)
            .onChange(of: launchAtLogin) { _ in
        }
    }
    HStack() {
        Text("Updates:")
            .alignmentGuide(.custom) { d in d[HorizontalAlignment.trailing] }
        Toggle("Allow Automatic Updates", isOn: $allowAutomaticUpdates)
            .onChange(of: allowAutomaticUpdates) { _ in
        }
    }
}
.font(.custom("SFProText-Medium", size: 12))
.padding()

gives you…

enter image description here