4

I have the following view for each of the cells used in the List view....:

var body: some View {

    VStack {
        
        HStack {
            Text("item: \(item.name)")
            Text("Some text")
            Spacer()
        }
        
        HStack {
            Image(systemName: "squareshape.fill")
                .resizable()
                .frame(width: 30, height: 30)
            
            Spacer()
        }
        
    }

}

Looks like this:

enter image description here

I want to align the black square to the Some text leading edge found in the previous HStack. I annotated the image to visually show where the black square should land for clarity.

I have looked at a couple of similar questions that might have the solution in it but I haven't been able to apply what I saw to my need here yet. I believe I need to use alignment guides, but, I am not sure how to actually apply such change.

I think I could break the layout out differently where I could be using VStacks etc... but, I want to know how to tell a view to align itself to another in this case across HStacks...

How could I accomplish what outlined?

1 Answer 1

6

Here is a demo of possible approach - based on custom alignment guides, ie. applying same custom alignment guide to different views makes them aligned to/by that guide. (Actually you don't need second HStack for this scenario).

Tested with Xcode 12.5 / iOS 14.5

demo

struct ContentView: View {
    var body: some View {
        List(0..<10) {
            RowView(item: $0)
        }
    }
}

extension HorizontalAlignment {
   private enum MyLeadingAlignment: AlignmentID {
      static func defaultValue(in dimensions: ViewDimensions) -> CGFloat {
         return dimensions[HorizontalAlignment.leading]
      }
   }
   static let myLeading = HorizontalAlignment(MyLeadingAlignment.self)
}

struct RowView: View {
    let item: Int
    var body: some View {

        VStack(alignment: .myLeading) {
            HStack {
                Text("item: \(item)")
                Text("Some text")
                    .alignmentGuide(.myLeading) { $0[.leading] } // << here !!
                Spacer()
            }
            Image(systemName: "squareshape.fill")
                .resizable()
                .frame(width: 30, height: 30)
                .alignmentGuide(.myLeading) { $0[.leading] } // << here !!
        }
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

why do I have to specify this "VStack(alignment: .myLeading)", does that mean that if I want to use a custom alignment, the container has to pass it down first? And if the tis the case, then I can only have one custom alignment per container?
Not a right solution. This might work for this specific case but if you replace Image with Text that has very long text, then views will be pushed outside of the parent from both start and end

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.