skip to Main Content

I have the following code:

struct ContentView: View {
    @State var isOn: Bool = false

    var body: some View {
        HStack(alignment: .top) {
            Toggle(isOn: $isOn) {
                Text("Hello")
            }

            Text("The quick brown fox jumped over the lazy dog")

            Spacer()

            Button("Go") {
                print("Knock knock.")
            }
            .padding()
        }
        .padding()
    }
}

Which results in:

Result

How do I vertically align the top line: The quick brown fox and Go with desiredly positioned Hello?

Of course I can manually tune the alignment with hard-coded .offset(); I have this now in my code. But that’s ugly and will fall apart if I’d change the font size(s) for example. I’m looking for a proper method without hard-code values.

Isn’t this possible with SwiftUI alignment features?

2

Answers


  1. [Updated]

    If you want to align vertically then you need to change your Hstack Alignment from .center to .top. From image below you can see toggle Text and Text are align horizontally.

    struct ContentView: View {
        
        @State var isOn: Bool = false
    
          var body: some View {
              HStack(alignment: .top) {
                  HStack(alignment: .top) {
                      Text("Hello")
                      Toggle(isOn: $isOn) {
                          
                      }
                  }
    
                  Text("The quick brown fox jumped over the lazy dog")
    
                  Spacer()
    
                  Button("Go") {
                      print("Knock knock.")
                  }
                  .padding()
              }
              .padding()
          }
    }
    

    enter image description here

    Login or Signup to reply.
  2. Here is one approach (the Toggle button toggles background colors on/off):

    import SwiftUI
    
    struct ContentView: View {
        
        @State var isOn: Bool = false
    
        @State var c1: Color = Color(red: 1.00, green: 0.75, blue: 0.75)
        @State var c2: Color = Color(red: 0.75, green: 1.00, blue: 0.75)
        @State var c3: Color = Color(red: 1.00, green: 1.00, blue: 0.00)
        @State var c4: Color = Color(red: 0.80, green: 1.00, blue: 0.75)
        @State var c5: Color = Color(red: 0.75, green: 0.75, blue: 0.25)
        
        var body: some View {
            
            HStack(alignment: .top) {
                    
                Spacer()
                
                Toggle(isOn: $isOn) {
                    Text("Hello")
                        .background(isOn ? c1 : .clear)
                }
                .background(isOn ? c2 : .clear)
                .offset(CGSize(width: 0.0, height: -5.0))
                
                Text("The quick brown fox jumped over the lazy dog")
                    .background(isOn ? c3 : .clear)
                    
                Spacer()
                
                Button("Go") {
                    print("Knock knock.")
                }
                .background(isOn ? c4 : .clear)
                
                Spacer()
                
            }
            .background(isOn ? c5 : .clear)
            .padding()
            
        }
    
    }
    

    Output (red line is added after, to show the text baselines):

    enter image description here

    You would probably want to use GeometryReader to calculate the correct offset, rather than using the hard-coded y: -5.0


    Editafter quick searching for dynamic sizing instead of hard-coded y: -5.0

    Based on info found here: https://stackoverflow.com/a/63050004/6257435

    Looks like custom .alignmentGuide is what you need:

    import SwiftUI
    
    extension VerticalAlignment {
        private enum XAlignment : AlignmentID {
            static func defaultValue(in d: ViewDimensions) -> CGFloat {
                return d[VerticalAlignment.top]
            }
        }
        static let xAlignment = VerticalAlignment(XAlignment.self)
    }
    
    struct ContentView: View {
        
        @State var isOn: Bool = true
    
        @State var c1: Color = Color(red: 1.00, green: 0.75, blue: 0.75)
        @State var c2: Color = Color(red: 0.75, green: 1.00, blue: 0.75)
        @State var c3: Color = Color(red: 1.00, green: 1.00, blue: 0.00)
        @State var c4: Color = Color(red: 0.80, green: 1.00, blue: 0.75)
        @State var c5: Color = Color(red: 0.75, green: 0.75, blue: 0.25)
        
        var body: some View {
            
            HStack(alignment: .xAlignment) {
    
                Spacer()
                
                Toggle(isOn: $isOn) {
                    Text("Hello")
                        .background(isOn ? c1 : .clear)
                }
                    .background(isOn ? c2 : .clear)
                    .alignmentGuide(.xAlignment) { $0.height * 0.5 }
                
                Text("The quick brown fox jumped over the lazy dog")
                    .background(isOn ? c3 : .clear)
                    .alignmentGuide(.xAlignment) {
                        ($0.height - ($0[.lastTextBaseline] - $0[.firstTextBaseline])) * 0.5
                    }
    
                Spacer()
                
                Button("Go") {
                    print("Knock knock.")
                }
                .background(isOn ? c4 : .clear)
                .alignmentGuide(.xAlignment) { $0.height * 0.5 }
    
                Spacer()
    
            }
            .background(isOn ? c5 : .clear)
            .padding()
    
        }
    
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search